1 #include <gtest/gtest.h> 3 #include <boost/filesystem.hpp> 4 #include <boost/process.hpp> 6 #include "config/config.h" 7 #include "http/httpclient.h" 8 #include "package_manager/dockerappmanager.h" 9 #include "package_manager/packagemanagerfactory.h" 10 #include "package_manager/packagemanagerinterface.h" 11 #include "primary/sotauptaneclient.h" 12 #include "storage/invstorage.h" 13 #include "test_utils.h" 14 #include "uptane/fetcher.h" 16 static std::string repo_server =
"http://127.0.0.1:";
17 static std::string treehub_server =
"http://127.0.0.1:";
18 static boost::filesystem::path test_sysroot;
19 static boost::filesystem::path uptane_gen;
25 static std::string new_rev;
27 extern "C" OstreeDeployment* ostree_sysroot_get_booted_deployment(OstreeSysroot*
self) {
29 static GObjectUniquePtr<OstreeDeployment> dep;
31 dep.reset(ostree_deployment_new(0,
"dummy-os", ostree_deployment.rev.c_str(), ostree_deployment.serial,
32 ostree_deployment.rev.c_str(), ostree_deployment.serial));
36 extern "C" const char* ostree_deployment_get_csum(OstreeDeployment*
self) {
38 return ostree_deployment.rev.c_str();
41 static void progress_cb(
const Uptane::Target& target,
const std::string& description,
unsigned int progress) {
43 LOG_INFO <<
"progress_cb " << target <<
" " << progress;
46 static std::unique_ptr<boost::process::child> create_repo(
const boost::filesystem::path& repo_path) {
47 std::string port = TestUtils::getFreePort();
49 auto p = std_::make_unique<boost::process::child>(
"src/libaktualizr/package_manager/dockerapp_test_repo.sh",
50 uptane_gen, repo_path, port);
51 TestUtils::waitForServer(repo_server +
"/");
57 config.pacman.type = PACKAGE_MANAGER_OSTREEDOCKERAPP;
58 config.pacman.sysroot = test_sysroot;
60 config.storage.path = dir.Path();
62 std::shared_ptr<INvStorage> storage = INvStorage::newStorage(config.storage);
63 auto pacman = PackageManagerFactory::makePackageManager(config.pacman, config.bootloader, storage,
nullptr);
69 config.pacman.type = PACKAGE_MANAGER_OSTREEDOCKERAPP;
70 config.pacman.sysroot = test_sysroot.string();
71 config.pacman.ostree_server = treehub_server;
72 config.pacman.extra[
"docker_apps_root"] =
"apps-root";
73 config.pacman.extra[
"docker_apps"] =
"app1 app2";
74 config.pacman.extra[
"docker_app_bin"] =
"dab";
75 config.pacman.extra[
"docker_compose_bin"] =
"compose";
78 ASSERT_TRUE(dacfg.docker_prune);
79 ASSERT_EQ(2, dacfg.docker_apps.size());
80 ASSERT_EQ(
"app1", dacfg.docker_apps[0]);
81 ASSERT_EQ(
"app2", dacfg.docker_apps[1]);
82 ASSERT_EQ(
"apps-root", dacfg.docker_apps_root);
83 ASSERT_EQ(
"dab", dacfg.docker_app_bin);
84 ASSERT_EQ(
"compose", dacfg.docker_compose_bin);
86 config.pacman.extra[
"docker_prune"] =
"0";
88 ASSERT_FALSE(dacfg.docker_prune);
90 config.pacman.extra[
"docker_prune"] =
"FALSE";
92 ASSERT_FALSE(dacfg.docker_prune);
96 std::string sha = Utils::readFile(test_sysroot /
"ostree/repo/refs/heads/ostree/1/1/0",
true);
97 Json::Value target_json;
98 target_json[
"hashes"][
"sha256"] = sha;
99 target_json[
"custom"][
"targetFormat"] =
"OSTREE";
100 target_json[
"length"] = 0;
101 target_json[
"custom"][
"docker_apps"][
"app1"][
"filename"] =
"foo.dockerapp";
103 target_json[
"custom"][
"docker_apps"][
"app1"][
"uri"] =
"http://foo.com";
107 auto repo = temp_dir.Path();
108 auto repod = create_repo(repo);
110 ostree_deployment.serial = 1;
111 ostree_deployment.rev = sha;
113 boost::filesystem::path apps_root = temp_dir /
"docker_apps";
116 config.pacman.type = PACKAGE_MANAGER_OSTREEDOCKERAPP;
117 config.pacman.sysroot = test_sysroot.string();
118 config.pacman.ostree_server = treehub_server;
119 config.pacman.extra[
"docker_apps_root"] = apps_root.string();
120 config.pacman.extra[
"docker_apps"] =
"app1 app2";
121 config.pacman.extra[
"docker_app_bin"] = config.pacman.extra[
"docker_compose_bin"] =
122 "src/libaktualizr/package_manager/docker_fake.sh";
123 config.uptane.repo_server = repo_server +
"/repo/repo";
125 config.storage.path = dir.Path();
129 boost::filesystem::create_directories(apps_root /
"delete-this-app");
132 boost::filesystem::create_directories(apps_root /
"app2");
134 std::shared_ptr<INvStorage> storage = INvStorage::newStorage(config.storage);
135 storage->savePrimaryInstalledVersion(target, InstalledVersionUpdateMode::kCurrent);
136 KeyManager keys(storage, config.keymanagerConfig());
137 auto client = std_::make_unique<SotaUptaneClient>(config, storage);
138 ASSERT_NO_THROW(client->updateImageMeta());
140 std::string targets = Utils::readFile(repo /
"repo/repo/targets.json");
141 LOG_INFO <<
"Repo targets " << targets;
143 bool result = client->package_manager_->fetchTarget(target, *(client->uptane_fetcher), keys, progress_cb,
nullptr);
146 auto hashes = std::vector<Hash>{
147 Hash(Hash::Type::kSha256,
"dfca385c923400228c8ddd3c2d572919985e48a9409a2d71dab33148017231c3"),
148 Hash(Hash::Type::kSha512,
149 "76b183d51f53613a450825afc6f984077b68ae7b321ba041a2b3871f3c25a9a20d964ad0b60352e5fdd09b78fd53879f4e3" 150 "fa3dcc8335b26d3bbf455803d2ecb")};
151 Uptane::Target app_target(
"foo.dockerapp", Uptane::EcuMap{}, hashes, 8);
152 ASSERT_TRUE(storage->checkTargetFile(app_target));
154 client->package_manager_->install(target);
155 std::string content = Utils::readFile(apps_root /
"app1/docker-compose.yml");
156 ASSERT_EQ(
"DOCKER-APP RENDER OUTPUT\nfake contents of a docker app\n", content);
159 ASSERT_FALSE(boost::filesystem::exists(apps_root /
"delete-this-app"));
160 ASSERT_FALSE(boost::filesystem::exists(apps_root /
"app2"));
161 ASSERT_TRUE(boost::filesystem::exists(apps_root /
"docker-compose-down-called"));
163 setenv(
"DOCKER_APP_FAIL",
"1", 1);
164 result = client->package_manager_->fetchTarget(target, *(client->uptane_fetcher), keys, progress_cb,
nullptr);
165 ASSERT_FALSE(result);
170 unsetenv(
"DOCKER_APP_FAIL");
171 std::string sha = Utils::readFile(test_sysroot /
"ostree/repo/refs/heads/ostree/1/1/0",
true);
172 Json::Value target_json;
173 target_json[
"hashes"][
"sha256"] = sha;
174 target_json[
"custom"][
"targetFormat"] =
"OSTREE";
175 target_json[
"length"] = 0;
176 target_json[
"custom"][
"docker_apps"][
"app1"][
"uri"] =
"hub.docker.io/user/hello@sha256:deadbeef";
178 target_json[
"custom"][
"docker_apps"][
"app1"][
"filename"] =
"foo.dockerapp";
181 ostree_deployment.serial = 1;
182 ostree_deployment.rev = sha;
187 boost::filesystem::path docker =
188 boost::filesystem::system_complete(
"src/libaktualizr/package_manager/docker_fake.sh");
189 ASSERT_EQ(0, symlink(docker.c_str(), (temp_dir.Path() /
"docker").c_str()));
190 std::string path(temp_dir.PathString() +
":" + getenv(
"PATH"));
191 setenv(
"PATH", path.c_str(), 1);
194 boost::filesystem::path apps_root = temp_dir /
"docker_apps";
196 config.pacman.type = PACKAGE_MANAGER_OSTREEDOCKERAPP;
197 config.pacman.sysroot = test_sysroot;
198 config.pacman.extra[
"docker_apps_root"] = apps_root.string();
199 config.pacman.extra[
"docker_apps"] =
"app1 app2";
200 config.pacman.extra[
"docker_compose_bin"] =
"src/libaktualizr/package_manager/docker_fake.sh";
201 config.pacman.ostree_server = treehub_server;
202 config.uptane.repo_server = repo_server +
"/repo/repo";
204 config.storage.path = dir.Path();
211 boost::filesystem::create_directories(apps_root /
"app2");
213 std::shared_ptr<INvStorage> storage = INvStorage::newStorage(config.storage);
214 storage->savePrimaryInstalledVersion(target, InstalledVersionUpdateMode::kCurrent);
215 KeyManager keys(storage, config.keymanagerConfig());
216 auto client = std_::make_unique<SotaUptaneClient>(config, storage);
218 ASSERT_TRUE(client->package_manager_->fetchTarget(target, *(client->uptane_fetcher), keys, progress_cb,
nullptr));
219 std::string content = Utils::readFile(temp_dir /
"docker-app-pull");
220 ASSERT_EQ(
"PULL CALLED app pull hub.docker.io/user/hello@sha256:deadbeef\n", content);
222 client->package_manager_->install(target);
223 content = Utils::readFile(apps_root /
"app1/docker-compose.yml");
224 ASSERT_EQ(
"FAKE CONTENT FOR IMAGE RENDER\nhub.docker.io/user/hello@sha256:deadbeef\n", content);
227 ASSERT_FALSE(boost::filesystem::exists(apps_root /
"delete-this-app"));
228 ASSERT_FALSE(boost::filesystem::exists(apps_root /
"app2"));
229 ASSERT_TRUE(boost::filesystem::exists(apps_root /
"docker-compose-down-called"));
233 int main(
int argc,
char** argv) {
234 ::testing::InitGoogleTest(&argc, argv);
237 std::cerr <<
"Error: " << argv[0]
238 <<
" requires the path to an OSTree sysroot and uptane-generator as an input argument.\n";
241 uptane_gen = argv[2];
243 std::string port = TestUtils::getFreePort();
244 treehub_server += port;
245 boost::process::child server_process(
"tests/fake_http_server/fake_test_server.py", port);
249 int r = system((std::string(
"cp -r ") + argv[1] + std::string(
" ") + temp_dir.PathString()).c_str());
253 test_sysroot = (temp_dir.Path() /
"ostree_repo").
string();
255 TestUtils::waitForServer(treehub_server +
"/");
257 return RUN_ALL_TESTS();
Configuration object for an aktualizr instance running on a Primary ECU.
The hash of a file or Uptane metadata.
Results of libaktualizr API calls.