3 #include "dockerappmanager.h"
4 #include "libaktualizr/packagemanagerfactory.h"
38 : name(std::move(app_name)),
39 app_root(config.docker_apps_root / name),
40 app_params(config.docker_app_params),
41 compose_bin(boost::filesystem::canonical(config.docker_compose_bin).string()) {}
45 static bool cmd_streaming(
const std::string &cmd) {
return std::system(cmd.c_str()) == 0; }
47 bool fetch(
const std::string &app_uri) {
return cmd_streaming(
"docker app pull " + app_uri); }
49 bool start(
const std::string &app_uri) {
50 boost::filesystem::create_directories(app_root);
51 std::string cmd(
"cd " + app_root.string() +
" && docker app image render -o docker-compose.yml " + app_uri);
52 if (!app_params.empty()) {
53 cmd +=
" --parameters-file " + app_params.string();
55 if (!cmd_streaming(cmd)) {
59 return cmd_streaming(
"cd " + app_root.string() +
" && " + compose_bin +
" up --remove-orphans -d");
63 if (cmd_streaming(
"cd " + app_root.string() +
" && " + compose_bin +
" down")) {
64 boost::filesystem::remove_all(app_root);
66 LOG_ERROR <<
"docker-compose was unable to bring down: " << app_root;
71 boost::filesystem::path app_root;
72 boost::filesystem::path app_params;
73 std::string compose_bin;
76 std::vector<std::pair<std::string, std::string>> DockerAppBundles::iterate_apps(
const Uptane::Target &target)
const {
77 auto apps = target.custom_data()[
"docker_apps"];
82 repo.checkMetaOffline(*storage_);
83 }
catch (
const std::exception &e) {
88 LOG_DEBUG <<
"Detected an update target from Director with no docker-apps data";
90 if (t.MatchTarget(target)) {
91 LOG_DEBUG <<
"Found the match " << t;
92 apps = t.custom_data()[
"docker_apps"];
98 std::vector<std::pair<std::string, std::string>> bundles;
99 for (Json::ValueIterator i = apps.begin(); i != apps.end(); ++i) {
100 if ((*i).isObject() && (*i).isMember(
"uri")) {
101 for (
const auto &app : dappcfg_.docker_apps) {
102 if (i.key().asString() == app) {
103 bundles.emplace_back(i.key().asString(), (*i)[
"uri"].asString());
107 }
else if ((*i).isObject() && (*i).isMember(
"filename")) {
108 LOG_TRACE <<
"Skipping old docker app format for " << i.key().asString() <<
" -> " << *i;
110 LOG_ERROR <<
"Invalid custom data for docker-app: " << i.key().asString() <<
" -> " << *i;
118 if (!OstreeManager::fetchTarget(target, fetcher, keys, progress_cb, token)) {
122 LOG_INFO <<
"Looking for DockerApps to fetch";
124 for (
const auto &pair : iterate_apps(target)) {
125 LOG_INFO <<
"Fetching " << pair.first <<
" -> " << pair.second;
126 if (!
AppBundle(pair.first, dappcfg_).fetch(pair.second)) {
136 if (current.sha256Hash() != target.sha256Hash()) {
137 res = OstreeManager::install(target);
139 LOG_ERROR <<
"Failed to install OSTree target, skipping Docker Apps";
143 LOG_INFO <<
"Target " << target.sha256Hash() <<
" is same as current";
147 handleRemovedApps(target);
148 for (
const auto &pair : iterate_apps(target)) {
149 LOG_INFO <<
"Installing " << pair.first <<
" -> " << pair.second;
150 if (!
AppBundle(pair.first, dappcfg_).start(pair.second)) {
155 if (dappcfg_.docker_prune) {
156 LOG_INFO <<
"Pruning unused docker images";
159 if (std::system(
"docker image prune -a -f --filter=\"label!=aktualizr-no-prune\"") != 0) {
160 LOG_WARNING <<
"Unable to prune unused docker images";
172 void DockerAppBundles::handleRemovedApps(
const Uptane::Target &target)
const {
173 if (!boost::filesystem::is_directory(dappcfg_.docker_apps_root)) {
174 LOG_DEBUG <<
"dappcfg_.docker_apps_root does not exist";
178 std::vector<std::string> target_apps = target.custom_data()[
"docker_apps"].getMemberNames();
180 for (
auto &entry : boost::make_iterator_range(boost::filesystem::directory_iterator(dappcfg_.docker_apps_root), {})) {
181 if (boost::filesystem::is_directory(entry)) {
182 std::string name = entry.path().filename().native();
183 if (std::find(dappcfg_.docker_apps.begin(), dappcfg_.docker_apps.end(), name) == dappcfg_.docker_apps.end()) {
184 LOG_WARNING <<
"Docker App(" << name
185 <<
") installed, but is now removed from configuration. Removing from system";
188 if (std::find(target_apps.begin(), target_apps.end(), name) == target_apps.end()) {
189 LOG_WARNING <<
"Docker App(" << name
190 <<
") configured, but not defined in installation target. Removing from system";