3 #include "dockerappmanager.h"
4 #include "libaktualizr/packagemanagerfactory.h"
46 : name(std::move(app_name)),
47 app_root(config.docker_apps_root / name),
48 app_params(config.docker_app_params),
49 app_bin(config.docker_app_bin),
50 compose_bin(config.docker_compose_bin) {}
52 bool render(
const std::string &app_content,
bool persist) {
53 auto bin = boost::filesystem::canonical(app_bin).string();
54 Utils::writeFile(app_root / (name +
".dockerapp"), app_content);
55 std::string cmd(
"cd " + app_root.string() +
" && " + bin +
" render " + name);
56 if (!app_params.empty()) {
57 cmd +=
" --parameters-file " + app_params.string();
60 cmd +=
" -o " + (app_root /
"docker-compose.yml").
string();
63 if (Utils::shell(cmd, &output,
true) != 0) {
64 LOG_ERROR <<
"Unable to run " << cmd <<
" output:\n" << output;
71 auto bin = boost::filesystem::canonical(compose_bin).string();
72 std::string cmd(
"cd " + app_root.string() +
" && " + bin +
" pull");
73 return std::system(cmd.c_str()) == 0;
81 auto bin = boost::filesystem::canonical(compose_bin).string();
82 std::string cmd(
"cd " + app_root.string() +
" && " + bin +
" up --remove-orphans -d");
83 return std::system(cmd.c_str()) == 0;
87 auto bin = boost::filesystem::canonical(compose_bin).string();
88 std::string cmd(
"cd " + app_root.string() +
" && " + bin +
" down");
89 if (std::system(cmd.c_str()) == 0) {
90 boost::filesystem::remove_all(app_root);
92 LOG_ERROR <<
"docker-compose was unable to bring down: " << app_root;
97 boost::filesystem::path app_root;
98 boost::filesystem::path app_params;
99 boost::filesystem::path app_bin;
100 boost::filesystem::path compose_bin;
103 bool DockerAppStandalone::iterate_apps(
const Uptane::Target &target,
const DockerAppCb &cb)
const {
104 auto apps = target.custom_data()[
"docker_apps"];
110 repo.checkMetaOffline(*storage_);
111 }
catch (
const std::exception &e) {
116 LOG_DEBUG <<
"Detected an update target from Director with no docker-apps data";
118 if (t.MatchTarget(target)) {
119 LOG_DEBUG <<
"Found the match " << t;
120 apps = t.custom_data()[
"docker_apps"];
127 for (Json::ValueIterator i = apps.begin(); i != apps.end(); ++i) {
128 if ((*i).isObject() && (*i).isMember(
"filename")) {
129 for (
const auto &app : dappcfg_.docker_apps) {
130 if (i.key().asString() == app && (*i)[
"filename"].asString() == t.filename()) {
136 }
else if ((*i).isObject() && (*i).isMember(
"uri")) {
137 LOG_TRACE <<
"Skipping docker app bundle format for " << i.key().asString() <<
" -> " << *i;
139 LOG_ERROR <<
"Invalid custom data for docker-app: " << i.key().asString() <<
" -> " << *i;
148 if (!OstreeManager::fetchTarget(target, fetcher, keys, progress_cb, token)) {
152 LOG_INFO <<
"Looking for DockerApps to fetch";
153 auto cb = [
this, &fetcher, &keys, progress_cb, token](
const std::string &app,
const Uptane::Target &app_target) {
154 LOG_INFO <<
"Fetching " << app <<
" -> " << app_target;
156 if (!PackageManagerInterface::fetchTarget(app_target, fetcher, keys, progress_cb, token)) {
159 std::stringstream ss;
160 ss << openTargetFile(app_target).rdbuf();
162 return dapp.render(ss.str(),
true) && dapp.fetch();
164 return iterate_apps(target, cb);
170 if (current.sha256Hash() != target.sha256Hash()) {
171 res = OstreeManager::install(target);
173 LOG_ERROR <<
"Failed to install OSTree target, skipping Docker Apps";
177 LOG_INFO <<
"Target " << target.sha256Hash() <<
" is same as current";
181 handleRemovedApps(target);
182 auto cb = [
this](
const std::string &app,
const Uptane::Target &app_target) {
183 LOG_INFO <<
"Installing " << app <<
" -> " << app_target;
186 if (!iterate_apps(target, cb)) {
190 if (dappcfg_.docker_prune) {
191 LOG_INFO <<
"Pruning unused docker images";
194 if (std::system(
"docker image prune -a -f --filter=\"label!=aktualizr-no-prune\"") != 0) {
195 LOG_WARNING <<
"Unable to prune unused docker images";
206 void DockerAppStandalone::handleRemovedApps(
const Uptane::Target &target)
const {
207 if (!boost::filesystem::is_directory(dappcfg_.docker_apps_root)) {
208 LOG_DEBUG <<
"dappcfg_.docker_apps_root does not exist";
212 std::vector<std::string> target_apps = target.custom_data()[
"docker_apps"].getMemberNames();
214 for (
auto &entry : boost::make_iterator_range(boost::filesystem::directory_iterator(dappcfg_.docker_apps_root), {})) {
215 if (boost::filesystem::is_directory(entry)) {
216 std::string name = entry.path().filename().native();
217 if (std::find(dappcfg_.docker_apps.begin(), dappcfg_.docker_apps.end(), name) == dappcfg_.docker_apps.end()) {
218 LOG_WARNING <<
"Docker App(" << name
219 <<
") installed, but is now removed from configuration. Removing from system";
222 if (std::find(target_apps.begin(), target_apps.end(), name) == target_apps.end()) {
223 LOG_WARNING <<
"Docker App(" << name
224 <<
") configured, but not defined in installation target. Removing from system";