1 #include "dockerappmanager.h"
2 #include "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 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"];
81 repo.checkMetaOffline(*storage_);
84 LOG_DEBUG <<
"Detected an update target from Director with no docker-apps data";
86 if (t.MatchTarget(target)) {
87 LOG_DEBUG <<
"Found the match " << t;
88 apps = t.custom_data()[
"docker_apps"];
94 std::vector<std::pair<std::string, std::string>> bundles;
95 for (Json::ValueIterator i = apps.begin(); i != apps.end(); ++i) {
96 if ((*i).isObject() && (*i).isMember(
"uri")) {
97 for (
const auto &app : dappcfg_.docker_apps) {
98 if (i.key().asString() == app) {
99 bundles.emplace_back(i.key().asString(), (*i)[
"uri"].asString());
103 }
else if ((*i).isObject() && (*i).isMember(
"filename")) {
104 LOG_TRACE <<
"Skipping old docker app format for " << i.key().asString() <<
" -> " << *i;
106 LOG_ERROR <<
"Invalid custom data for docker-app: " << i.key().asString() <<
" -> " << *i;
114 if (!OstreeManager::fetchTarget(target, fetcher, keys, progress_cb, token)) {
118 LOG_INFO <<
"Looking for DockerApps to fetch";
120 for (
const auto &pair : iterate_apps(target)) {
121 LOG_INFO <<
"Fetching " << pair.first <<
" -> " << pair.second;
122 if (!
AppBundle(pair.first, dappcfg_).fetch(pair.second)) {
130 auto res = OstreeManager::install(target);
131 handleRemovedApps(target);
132 for (
const auto &pair : iterate_apps(target)) {
133 LOG_INFO <<
"Installing " << pair.first <<
" -> " << pair.second;
134 if (!
AppBundle(pair.first, dappcfg_).start(pair.second)) {
139 if (dappcfg_.docker_prune) {
140 LOG_INFO <<
"Pruning unused docker images";
143 if (std::system(
"docker image prune -a -f") != 0) {
144 LOG_WARNING <<
"Unable to prune unused docker images";
156 void DockerAppBundles::handleRemovedApps(
const Uptane::Target &target)
const {
157 if (!boost::filesystem::is_directory(dappcfg_.docker_apps_root)) {
158 LOG_DEBUG <<
"dappcfg_.docker_apps_root does not exist";
162 std::vector<std::string> target_apps = target.custom_data()[
"docker_apps"].getMemberNames();
164 for (
auto &entry : boost::make_iterator_range(boost::filesystem::directory_iterator(dappcfg_.docker_apps_root), {})) {
165 if (boost::filesystem::is_directory(entry)) {
166 std::string name = entry.path().filename().native();
167 if (std::find(dappcfg_.docker_apps.begin(), dappcfg_.docker_apps.end(), name) == dappcfg_.docker_apps.end()) {
168 LOG_WARNING <<
"Docker App(" << name
169 <<
") installed, but is now removed from configuration. Removing from system";
172 if (std::find(target_apps.begin(), target_apps.end(), name) == target_apps.end()) {
173 LOG_WARNING <<
"Docker App(" << name
174 <<
") configured, but not defined in installation target. Removing from system";