You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ji...@apache.org on 2016/03/03 03:06:23 UTC
[3/3] mesos git commit: Added test for Appc image fetcher.
Added test for Appc image fetcher.
Added simple appc Fetcher test with mock HTTP image server.
Review: https://reviews.apache.org/r/43969/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/f0fb4046
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/f0fb4046
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/f0fb4046
Branch: refs/heads/master
Commit: f0fb404616d7af58083396b880a2b14abb7e671b
Parents: 6903c6e
Author: Jojy Varghese <jo...@mesosphere.io>
Authored: Wed Mar 2 18:04:15 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Wed Mar 2 18:04:15 2016 -0800
----------------------------------------------------------------------
.../containerizer/provisioner_appc_tests.cpp | 285 ++++++++++++++++---
1 file changed, 252 insertions(+), 33 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/f0fb4046/src/tests/containerizer/provisioner_appc_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/provisioner_appc_tests.cpp b/src/tests/containerizer/provisioner_appc_tests.cpp
index 9d9779a..86e1964 100644
--- a/src/tests/containerizer/provisioner_appc_tests.cpp
+++ b/src/tests/containerizer/provisioner_appc_tests.cpp
@@ -16,6 +16,8 @@
#include <string>
+#include <gmock/gmock.h>
+
#include <mesos/slave/isolator.hpp>
#include <process/gtest.hpp>
@@ -31,11 +33,14 @@
#include <mesos/appc/spec.hpp>
+#include "common/command_utils.hpp"
+
#include "slave/paths.hpp"
#include "slave/containerizer/mesos/provisioner/paths.hpp"
#include "slave/containerizer/mesos/provisioner/provisioner.hpp"
+#include "slave/containerizer/mesos/provisioner/appc/fetcher.hpp"
#include "slave/containerizer/mesos/provisioner/appc/paths.hpp"
#include "slave/containerizer/mesos/provisioner/appc/store.hpp"
@@ -43,6 +48,9 @@ using std::list;
using std::string;
using std::vector;
+using testing::_;
+using testing::Return;
+
using namespace process;
using namespace mesos::internal::slave::appc;
@@ -133,8 +141,11 @@ protected:
// directory. The directory structure reflects the Appc image spec.
//
// @param storeDir Path to the store directory where all images are stored.
+ // @param manifest Manifest JSON to be used for the test image.
// @return Path to the test image directory.
- Try<string> createTestImage(const string& storeDir)
+ Try<string> createTestImage(
+ const string& storeDir,
+ const JSON::Value& manifest)
{
Try<Nothing> mkdir = os::mkdir(storeDir, true);
if (mkdir.isError()) {
@@ -147,32 +158,6 @@ protected:
// |--<id>
// |--manifest
// |--rootfs/tmp/test
- JSON::Value manifest = JSON::parse(
- "{"
- " \"acKind\": \"ImageManifest\","
- " \"acVersion\": \"0.6.1\","
- " \"name\": \"foo.com/bar\","
- " \"labels\": ["
- " {"
- " \"name\": \"version\","
- " \"value\": \"1.0.0\""
- " },"
- " {"
- " \"name\": \"arch\","
- " \"value\": \"amd64\""
- " },"
- " {"
- " \"name\": \"os\","
- " \"value\": \"linux\""
- " }"
- " ],"
- " \"annotations\": ["
- " {"
- " \"name\": \"created\","
- " \"value\": \"1438983392\""
- " }"
- " ]"
- "}").get();
// The 'imageId' below has the correct format but it's not computed
// by hashing the tarball of the image. It's OK here as we assume
@@ -247,6 +232,39 @@ protected:
return appc;
}
+
+ // Abstracts the manifest accessor for the test fixture. This provides the
+ // ability for customizing manifests for fixtures.
+ virtual JSON::Value getManifest() const
+ {
+ return JSON::parse(
+ R"~(
+ {
+ "acKind": "ImageManifest",
+ "acVersion": "0.6.1",
+ "name": "foo.com/bar",
+ "labels": [
+ {
+ "name": "version",
+ "value": "1.0.0"
+ },
+ {
+ "name": "arch",
+ "value": "amd64"
+ },
+ {
+ "name": "os",
+ "value": "linux"
+ }
+ ],
+ "annotations": [
+ {
+ "name": "created",
+ "value": "1438983392"
+ }
+ ]
+ })~").get();
+ }
};
@@ -258,7 +276,9 @@ TEST_F(AppcStoreTest, Recover)
Try<Owned<slave::Store>> store = Store::create(flags);
ASSERT_SOME(store);
- Try<string> createImage = createTestImage(flags.appc_store_dir);
+ Try<string> createImage = createTestImage(
+ flags.appc_store_dir,
+ getManifest());
ASSERT_SOME(createImage);
@@ -296,12 +316,12 @@ TEST_F(ProvisionerAppcTest, ROOT_Provision)
flags.image_provisioner_backend = "bind";
flags.work_dir = "work_dir";
- Fetcher fetcher;
-
Try<Owned<Provisioner>> provisioner = Provisioner::create(flags);
ASSERT_SOME(provisioner);
- Try<string> createImage = createTestImage(flags.appc_store_dir);
+ Try<string> createImage = createTestImage(
+ flags.appc_store_dir,
+ getManifest());
ASSERT_SOME(createImage);
@@ -363,11 +383,12 @@ TEST_F(ProvisionerAppcTest, Recover)
flags.image_provisioner_backend = "copy";
flags.work_dir = "work_dir";
- Fetcher fetcher;
Try<Owned<Provisioner>> provisioner1 = Provisioner::create(flags);
ASSERT_SOME(provisioner1);
- Try<string> createImage = createTestImage(flags.appc_store_dir);
+ Try<string> createImage = createTestImage(
+ flags.appc_store_dir,
+ getManifest());
ASSERT_SOME(createImage);
@@ -428,6 +449,204 @@ TEST_F(ProvisionerAppcTest, Recover)
EXPECT_FALSE(os::exists(containerDir));
}
+
+// Mock HTTP image server.
+class TestAppcImageServer : public Process<TestAppcImageServer>
+{
+public:
+ TestAppcImageServer() : ProcessBase("TestAppcImageServer") {}
+
+ void addRoute(const string& imageName)
+ {
+ route("/" + imageName, None(), &TestAppcImageServer::serve);
+ }
+
+ MOCK_METHOD1(serve, Future<http::Response>(const http::Request&));
+};
+
+
+// Test fixture that uses the mock HTTP image server. This fixture provides the
+// abstraction for creating and composing complex test cases for Appc image
+// fetcher and store.
+class AppcImageFetcherTest : public AppcStoreTest
+{
+protected:
+ // Custom implementation that overrides the host and port of the image name.
+ JSON::Value getManifest() const
+ {
+ string imageName = strings::format(
+ "%s:%d/TestAppcImageServer/image",
+ stringify(server.self().address.ip),
+ server.self().address.port).get();
+
+ return JSON::parse(
+ R"~(
+ {
+ "acKind": "ImageManifest",
+ "acVersion": "0.6.1",
+ "name": " + imageName + ",
+ "labels": [
+ {
+ "name": "version",
+ "value": "1.0.0"
+ },
+ {
+ "name": "arch",
+ "value": "amd64"
+ },
+ {
+ "name": "os",
+ "value": "linux"
+ }
+ ],
+ "annotations": [
+ {
+ "name": "created",
+ "value": "1438983392"
+ }
+ ]
+ })~").get();
+ }
+
+ // TODO(jojy): Currently only supports serving one image. Consider adding
+ // support serving any image on the server. One way to do this is to add a map
+ // of image name -> server path for each image.
+ Future<http::Response> serveImage()
+ {
+ http::OK response;
+
+ response.type = response.PATH;
+ response.path = imageBundlePath;
+ response.headers["Content-Type"] = "application/octet-stream";
+ response.headers["Content-Disposition"] = strings::format(
+ "attachment; filename=%s",
+ imageBundlePath).get();
+
+ return response;
+ }
+
+ // TODO(jojy): Currently just uses 'imageId' to prepare a image on
+ // the server. Consider adding more parameters(e.g, 'labels').
+ void prepareServerImage(const string& fileName, const string& imageId)
+ {
+ const Path serverDir(path::join(os::getcwd(), "server"));
+
+ Try<string> createImage = createTestImage(serverDir, getManifest());
+ ASSERT_SOME(createImage);
+
+ // Set image file path for the test.
+ imageBundlePath = path::join(serverDir, fileName);
+
+ const Path imageDir(path::join(serverDir, "images", imageId));
+
+ Future<Nothing> future = command::tar(
+ Path("."),
+ Path(imageBundlePath),
+ imageDir,
+ command::Compression::GZIP);
+
+ AWAIT_READY(future);
+
+ // Now add route on the server for the image.
+ server.addRoute(fileName);
+ }
+
+ virtual void SetUp()
+ {
+ TemporaryDirectoryTest::SetUp();
+
+ // Now spawn the image server.
+ spawn(server);
+ }
+
+ virtual void TearDown()
+ {
+ terminate(server);
+ wait(server);
+
+ TemporaryDirectoryTest::TearDown();
+ }
+
+ string imageBundlePath;
+ TestAppcImageServer server;
+};
+
+
+// Tests simple fetch functionality of the appc::Fetcher component.
+// The test fetches a test Appc image from the http server and
+// verifies its content. The image is served in 'tar + gzip' format.
+TEST_F(AppcImageFetcherTest, SimpleFetch)
+{
+ // Setup the image on the image server.
+ prepareServerImage(
+ "image-latest-linux-amd64.aci",
+ "sha512-e77d96aa0240eedf134b8c90baeaf76dca8e78691836301d7498c8402044604"
+ "2e797b296d6ab296e0954c2626bfb264322ebeb8f447dac4fac6511ea06bc61f0");
+
+ // Setup server.
+ EXPECT_CALL(server, serve(_))
+ .WillOnce(Return(serveImage()));
+
+ // Appc Image to be fetched.
+ const string imageName =
+ stringify(server.self().address) + "/TestAppcImageServer/image";
+
+ Image::Appc imageInfo;
+ imageInfo.set_name(imageName);
+
+ Label archLabel;
+ archLabel.set_key("arch");
+ archLabel.set_value("amd64");
+
+ Label osLabel;
+ osLabel.set_key("os");
+ osLabel.set_value("linux");
+
+ Labels labels;
+ labels.add_labels()->CopyFrom(archLabel);
+ labels.add_labels()->CopyFrom(osLabel);
+
+ imageInfo.mutable_labels()->CopyFrom(labels);
+
+ // Create image fetcher.
+ Try<Owned<uri::Fetcher>> uriFetcher = uri::fetcher::create();
+ ASSERT_SOME(uriFetcher);
+
+ slave::Flags flags;
+
+ Try<Owned<slave::appc::Fetcher>> fetcher =
+ slave::appc::Fetcher::create(flags, uriFetcher.get().share());
+
+ ASSERT_SOME(fetcher);
+
+ // Prepare fetch directory.
+ const Path imageFetchDir(path::join(os::getcwd(), "fetched-images"));
+
+ Try<Nothing> mkdir = os::mkdir(imageFetchDir);
+ ASSERT_SOME(mkdir);
+
+ // Now fetch the image.
+ AWAIT_READY(fetcher.get()->fetch(imageInfo, imageFetchDir));
+
+ // Verify that there is an image directory.
+ Try<list<string>> imageDirs = os::ls(imageFetchDir);
+ ASSERT_SOME(imageDirs);
+
+ // Verify that there is only ONE image directory.
+ ASSERT_EQ(1u, imageDirs.get().size());
+
+ // Verify that there is a roofs.
+ const Path imageRootfs(path::join(
+ imageFetchDir,
+ imageDirs.get().front(),
+ "rootfs"));
+
+ ASSERT_TRUE(os::exists(imageRootfs));
+
+ // Verify that the image fetched is the same as on the server.
+ ASSERT_SOME_EQ("test", os::read(path::join(imageRootfs, "tmp", "test")));
+}
+
} // namespace tests {
} // namespace internal {
} // namespace mesos {