TEST(AgentValidationTest, ContainerID) { ContainerID containerId; Option<Error> error; // No empty IDs. containerId.set_value(""); error = validation::container::validateContainerId(containerId); EXPECT_SOME(error); // No slashes. containerId.set_value("/"); error = validation::container::validateContainerId(containerId); EXPECT_SOME(error); containerId.set_value("\\"); error = validation::container::validateContainerId(containerId); EXPECT_SOME(error); // No spaces. containerId.set_value("redis backup"); error = validation::container::validateContainerId(containerId); EXPECT_SOME(error); // No periods. containerId.set_value("redis.backup"); error = validation::container::validateContainerId(containerId); EXPECT_SOME(error); // Cannot be '.'. containerId.set_value("."); error = validation::container::validateContainerId(containerId); EXPECT_SOME(error); // Cannot be '..'. containerId.set_value(".."); error = validation::container::validateContainerId(containerId); EXPECT_SOME(error); // Valid. containerId.set_value("redis"); error = validation::container::validateContainerId(containerId); EXPECT_NONE(error); // Valid with invalid parent (empty `ContainerID.value`). containerId.set_value("backup"); containerId.mutable_parent(); error = validation::container::validateContainerId(containerId); EXPECT_SOME(error); // Valid with valid parent. containerId.set_value("backup"); containerId.mutable_parent()->set_value("redis"); error = validation::container::validateContainerId(containerId); EXPECT_NONE(error); }
// This test verifies that the image specified in the volume will be // properly provisioned and mounted into the container if container // root filesystem is not specified. TEST_P(VolumeImageIsolatorTest, ROOT_ImageInVolumeWithoutRootFilesystem) { string registry = path::join(sandbox.get(), "registry"); AWAIT_READY(DockerArchive::create(registry, "test_image")); slave::Flags flags = CreateSlaveFlags(); flags.isolation = "filesystem/linux,volume/image,docker/runtime"; flags.docker_registry = registry; flags.docker_store_dir = path::join(sandbox.get(), "store"); flags.image_providers = "docker"; Fetcher fetcher(flags); Try<MesosContainerizer*> create = MesosContainerizer::create(flags, true, &fetcher); ASSERT_SOME(create); Owned<Containerizer> containerizer(create.get()); ContainerID containerId; containerId.set_value(id::UUID::random().toString()); ContainerInfo container = createContainerInfo( None(), {createVolumeFromDockerImage("rootfs", "test_image", Volume::RW)}); CommandInfo command = createCommandInfo("test -d rootfs/bin"); ExecutorInfo executor = createExecutorInfo( "test_executor", nesting ? createCommandInfo("sleep 1000") : command); if (!nesting) { executor.mutable_container()->CopyFrom(container); } string directory = path::join(flags.work_dir, "sandbox"); ASSERT_SOME(os::mkdir(directory)); Future<Containerizer::LaunchResult> launch = containerizer->launch( containerId, createContainerConfig(None(), executor, directory), map<string, string>(), None()); AWAIT_ASSERT_EQ(Containerizer::LaunchResult::SUCCESS, launch); Future<Option<ContainerTermination>> wait = containerizer->wait(containerId); if (nesting) { ContainerID nestedContainerId; nestedContainerId.mutable_parent()->CopyFrom(containerId); nestedContainerId.set_value(id::UUID::random().toString()); launch = containerizer->launch( nestedContainerId, createContainerConfig(command, container), map<string, string>(), None()); AWAIT_ASSERT_EQ(Containerizer::LaunchResult::SUCCESS, launch); wait = containerizer->wait(nestedContainerId); } AWAIT_READY(wait); ASSERT_SOME(wait.get()); ASSERT_TRUE(wait->get().has_status()); EXPECT_WEXITSTATUS_EQ(0, wait->get().status()); if (nesting) { Future<Option<ContainerTermination>> termination = containerizer->destroy(containerId); AWAIT_READY(termination); ASSERT_SOME(termination.get()); ASSERT_TRUE(termination->get().has_status()); EXPECT_WTERMSIG_EQ(SIGKILL, termination.get()->status()); } }
// This test verifies that the provisioner can recover the rootfses // for the child containers if there is no image specified for its // parent container. TEST_F(ProvisionerAppcTest, RecoverNestedContainerNoParentImage) { slave::Flags flags; flags.image_providers = "APPC"; flags.appc_store_dir = path::join(os::getcwd(), "store"); flags.image_provisioner_backend = COPY_BACKEND; flags.work_dir = path::join(sandbox.get(), "work_dir"); Try<Owned<Provisioner>> provisioner = Provisioner::create(flags); ASSERT_SOME(provisioner); Try<string> createImage = createTestImage( flags.appc_store_dir, getManifest()); ASSERT_SOME(createImage); // Recover. This is when the image in the store is loaded. AWAIT_READY(provisioner.get()->recover({})); Image image; image.mutable_appc()->CopyFrom(getTestImage()); ContainerID parent; ContainerID child; parent.set_value(UUID::random().toString()); child.set_value(UUID::random().toString()); child.mutable_parent()->CopyFrom(parent); AWAIT_READY(provisioner.get()->provision(child, image)); provisioner->reset(); // Create a new provisioner to recover the state from the container. provisioner = Provisioner::create(flags); ASSERT_SOME(provisioner); AWAIT_READY(provisioner.get()->recover({parent, child})); AWAIT_READY(provisioner.get()->provision(child, image)); const string provisionerDir = slave::paths::getProvisionerDir(flags.work_dir); string containerDir = slave::provisioner::paths::getContainerDir( provisionerDir, child); Future<bool> destroy = provisioner.get()->destroy(child); AWAIT_READY(destroy); EXPECT_TRUE(destroy.get()); EXPECT_FALSE(os::exists(containerDir)); containerDir = slave::provisioner::paths::getContainerDir( provisionerDir, parent); destroy = provisioner.get()->destroy(parent); AWAIT_READY(destroy); EXPECT_TRUE(destroy.get()); EXPECT_FALSE(os::exists(containerDir)); }
// This test verifies that the provisioner can provision an rootfs // from an image for a child container. TEST_F(ProvisionerAppcTest, ROOT_ProvisionNestedContainer) { slave::Flags flags; flags.image_providers = "APPC"; flags.appc_store_dir = path::join(os::getcwd(), "store"); flags.image_provisioner_backend = BIND_BACKEND; flags.work_dir = path::join(sandbox.get(), "work_dir"); Try<Owned<Provisioner>> provisioner = Provisioner::create(flags); ASSERT_SOME(provisioner); Try<string> createImage = createTestImage( flags.appc_store_dir, getManifest()); ASSERT_SOME(createImage); // Recover. This is when the image in the store is loaded. AWAIT_READY(provisioner.get()->recover({})); Image image; image.mutable_appc()->CopyFrom(getTestImage()); ContainerID parent; ContainerID child; parent.set_value(UUID::random().toString()); child.set_value(UUID::random().toString()); child.mutable_parent()->CopyFrom(parent); Future<slave::ProvisionInfo> provisionInfo = provisioner.get()->provision(child, image); AWAIT_READY(provisionInfo); const string provisionerDir = slave::paths::getProvisionerDir(flags.work_dir); const string containerDir = slave::provisioner::paths::getContainerDir( provisionerDir, child); Try<hashmap<string, hashset<string>>> rootfses = slave::provisioner::paths::listContainerRootfses( provisionerDir, child); ASSERT_SOME(rootfses); // Verify that the rootfs is successfully provisioned. ASSERT_TRUE(rootfses->contains(flags.image_provisioner_backend)); ASSERT_EQ(1u, rootfses->get(flags.image_provisioner_backend)->size()); EXPECT_EQ(*rootfses->get(flags.image_provisioner_backend)->begin(), Path(provisionInfo.get().rootfs).basename()); // TODO(jieyu): Verify that 'containerDir' is nested under its // parent container's 'containerDir'. Future<bool> destroy = provisioner.get()->destroy(child); AWAIT_READY(destroy); EXPECT_TRUE(destroy.get()); EXPECT_FALSE(os::exists(containerDir)); }