1 #include "dockerappmanager.h"
42 : name(std::move(app_name)),
43 app_root(config.docker_apps_root / name),
44 app_params(config.docker_app_params),
45 app_bin(config.docker_app_bin),
46 compose_bin(config.docker_compose_bin) {}
48 bool render(
const std::string &app_content,
bool persist) {
49 auto bin = boost::filesystem::canonical(app_bin).string();
50 Utils::writeFile(app_root / (name +
".dockerapp"), app_content);
51 std::string cmd(
"cd " + app_root.string() +
" && " + bin +
" render " + name);
52 if (!app_params.empty()) {
53 cmd +=
" --parameters-file " + app_params.string();
56 if (Utils::shell(cmd, &yaml,
true) != 0) {
57 LOG_ERROR <<
"Unable to run " << cmd <<
" output:\n" << yaml;
61 Utils::writeFile(app_root /
"docker-compose.yml", yaml);
71 auto bin = boost::filesystem::canonical(compose_bin).string();
72 std::string cmd(
"cd " + app_root.string() +
" && " + bin +
" up --remove-orphans -d");
73 return std::system(cmd.c_str()) == 0;
77 auto bin = boost::filesystem::canonical(compose_bin).string();
78 std::string cmd(
"cd " + app_root.string() +
" && " + bin +
" down");
79 if (std::system(cmd.c_str()) == 0) {
80 boost::filesystem::remove_all(app_root);
82 LOG_ERROR <<
"docker-compose was unable to bring down: " << app_root;
87 boost::filesystem::path app_root;
88 boost::filesystem::path app_params;
89 boost::filesystem::path app_bin;
90 boost::filesystem::path compose_bin;
93 bool DockerAppManager::iterate_apps(
const Uptane::Target &target,
const DockerAppCb &cb)
const {
94 auto apps = target.custom_data()[
"docker_apps"];
99 repo.checkMetaOffline(*storage_);
102 LOG_DEBUG <<
"Detected an update target from Director with no docker-apps data";
104 if (t.MatchTarget(target)) {
105 LOG_DEBUG <<
"Found the match " << t;
106 apps = t.custom_data()[
"docker_apps"];
113 for (Json::ValueIterator i = apps.begin(); i != apps.end(); ++i) {
114 if ((*i).isObject() && (*i).isMember(
"filename")) {
115 for (
const auto &app : config.docker_apps) {
116 if (i.key().asString() == app && (*i)[
"filename"].asString() == t.filename()) {
123 LOG_ERROR <<
"Invalid custom data for docker-app: " << i.key().asString() <<
" -> " << *i;
132 if (!OstreeManager::fetchTarget(target, fetcher, keys, progress_cb, token)) {
136 LOG_INFO <<
"Looking for DockerApps to fetch";
137 auto cb = [
this, &fetcher, &keys, progress_cb, token](
const std::string &app,
const Uptane::Target &app_target) {
138 LOG_INFO <<
"Fetching " << app <<
" -> " << app_target;
139 return PackageManagerInterface::fetchTarget(app_target, fetcher, keys, progress_cb, token);
141 return iterate_apps(target, cb);
145 auto res = OstreeManager::install(target);
146 handleRemovedApps(target);
147 auto cb = [
this](
const std::string &app,
const Uptane::Target &app_target) {
148 LOG_INFO <<
"Installing " << app <<
" -> " << app_target;
149 std::stringstream ss;
150 ss << *storage_->openTargetFile(app_target);
152 return dapp.render(ss.str(),
true) && dapp.start();
154 if (!iterate_apps(target, cb)) {
165 void DockerAppManager::handleRemovedApps(
const Uptane::Target &target)
const {
166 if (!boost::filesystem::is_directory(config.docker_apps_root)) {
167 LOG_DEBUG <<
"config.docker_apps_root does not exist";
171 std::vector<std::string> target_apps = target.custom_data()[
"docker_apps"].getMemberNames();
173 for (
auto &entry : boost::make_iterator_range(boost::filesystem::directory_iterator(config.docker_apps_root), {})) {
174 if (boost::filesystem::is_directory(entry)) {
175 std::string name = entry.path().filename().native();
176 if (std::find(config.docker_apps.begin(), config.docker_apps.end(), name) == config.docker_apps.end()) {
177 LOG_WARNING <<
"Docker App(" << name
178 <<
") installed, but is now removed from configuration. Removing from system";
181 if (std::find(target_apps.begin(), target_apps.end(), name) == target_apps.end()) {
182 LOG_WARNING <<
"Docker App(" << name
183 <<
") configured, but not defined in installation target. Removing from system";
190 TargetStatus DockerAppManager::verifyTarget(
const Uptane::Target &target)
const {
193 status = OstreeManager::verifyTarget(target);
194 if (status != TargetStatus::kGood) {
198 auto cb = [
this](
const std::string &app,
const Uptane::Target &app_target) {
199 LOG_INFO <<
"Verifying " << app <<
" -> " << app_target;
200 std::stringstream ss;
201 ss << *storage_->openTargetFile(app_target);
203 return dapp.render(ss.str(),
false);
205 if (!iterate_apps(target, cb)) {
206 return TargetStatus::kInvalid;
208 return TargetStatus::kGood;