Repository: mesos
Updated Branches:
  refs/heads/master 2a8de6255 -> 7a4a7a53b


Added validation of *_NESTED_CONTAINER calls in the agent API.

Review: https://reviews.apache.org/r/52100


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/7a4a7a53
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/7a4a7a53
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/7a4a7a53

Branch: refs/heads/master
Commit: 7a4a7a53b28fa90dcf7ba9626832b3d9b87f8b06
Parents: 31fb89f
Author: Benjamin Mahler <bmah...@apache.org>
Authored: Tue Sep 20 14:19:14 2016 -0700
Committer: Benjamin Mahler <bmah...@apache.org>
Committed: Wed Sep 21 23:07:08 2016 -0700

----------------------------------------------------------------------
 src/Makefile.am                      |   1 +
 src/slave/validation.cpp             |  62 +++++++++++-
 src/tests/slave_validation_tests.cpp | 157 ++++++++++++++++++++++++++++++
 3 files changed, 216 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/7a4a7a53/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 478fb5a..239e5af 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2132,6 +2132,7 @@ mesos_tests_SOURCES =                                     
        \
   tests/script.cpp                                             \
   tests/slave_authorization_tests.cpp                          \
   tests/slave_recovery_tests.cpp                               \
+  tests/slave_validation_tests.cpp                             \
   tests/slave_tests.cpp                                                \
   tests/sorter_tests.cpp                                       \
   tests/state_tests.cpp                                                \

http://git-wip-us.apache.org/repos/asf/mesos/blob/7a4a7a53/src/slave/validation.cpp
----------------------------------------------------------------------
diff --git a/src/slave/validation.cpp b/src/slave/validation.cpp
index d9c1aa8..62b2733 100644
--- a/src/slave/validation.cpp
+++ b/src/slave/validation.cpp
@@ -18,6 +18,7 @@
 
 #include <mesos/agent/agent.hpp>
 
+#include <stout/stringify.hpp>
 #include <stout/unreachable.hpp>
 #include <stout/uuid.hpp>
 
@@ -100,14 +101,67 @@ Option<Error> validate(
     case mesos::agent::Call::GET_TASKS:
       return None();
 
-    case mesos::agent::Call::LAUNCH_NESTED_CONTAINER:
-      return Error("Unimplemented");
+    case mesos::agent::Call::LAUNCH_NESTED_CONTAINER: {
+      if (!call.has_launch_nested_container()) {
+        return Error("Expecting 'launch_nested_container' to be present");
+      }
+
+      const mesos::agent::Call::LaunchNestedContainer& launchNestedContainer =
+        call.launch_nested_container();
+
+      // The `ContainerID` must be a RFC-4122 Version 4 UUID
+      // in standard string format.
+      Try<UUID> uuid = UUID::fromString(
+          launchNestedContainer.container_id().value());
+
+      if (uuid.isError()) {
+        return Error("'launch_nested_container.container_id.value' must be"
+                     " an RFC-4122 version 4 UUID in string format: " +
+                     uuid.error());
+      }
+
+      if (uuid->version() != UUID::version_random_number_based) {
+        return Error("Expected version 4 UUID but was version"
+                     " " + stringify(uuid->version()));
+      }
+
+      // A single parent `ContainerID` is expected, so that we know
+      // which container to place it underneath.
+      if (!launchNestedContainer.container_id().has_parent()) {
+        return Error("Expecting 'launch_nested_container.container_id.parent'"
+                     " to be present");
+      } else if (launchNestedContainer.container_id().parent().has_parent()) {
+        return Error("Expecting a single parent ContainerID but"
+                     " 'launch_nested_container.container_id.parent.parent'"
+                     " is set");
+      }
+
+      return None();
+    }
 
     case mesos::agent::Call::WAIT_NESTED_CONTAINER:
-      return Error("Unimplemented");
+      if (!call.has_wait_nested_container()) {
+        return Error("Expecting 'wait_nested_container' to be present");
+      }
+
+      if (call.wait_nested_container().container_id().has_parent()) {
+        return Error("Not expecting 
'wait_nested_container.container_id.parent'"
+                     " to be present");
+      }
+
+      return None();
 
     case mesos::agent::Call::KILL_NESTED_CONTAINER:
-      return Error("Unimplemented");
+      if (!call.has_kill_nested_container()) {
+        return Error("Expecting 'kill_nested_container' to be present");
+      }
+
+      if (call.kill_nested_container().container_id().has_parent()) {
+        return Error("Not expecting 
'kill_nested_container.container_id.parent'"
+                     " to be present");
+      }
+
+      return None();
   }
 
   UNREACHABLE();

http://git-wip-us.apache.org/repos/asf/mesos/blob/7a4a7a53/src/tests/slave_validation_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/slave_validation_tests.cpp 
b/src/tests/slave_validation_tests.cpp
new file mode 100644
index 0000000..ee59aee
--- /dev/null
+++ b/src/tests/slave_validation_tests.cpp
@@ -0,0 +1,157 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <gtest/gtest.h>
+
+#include <mesos/mesos.hpp>
+
+#include <mesos/agent/agent.hpp>
+
+#include <stout/error.hpp>
+#include <stout/gtest.hpp>
+#include <stout/option.hpp>
+#include <stout/uuid.hpp>
+
+#include "slave/slave.hpp"
+#include "slave/validation.hpp"
+
+namespace agent = mesos::agent;
+namespace validation = mesos::internal::slave::validation;
+
+using mesos::internal::slave::Slave;
+
+namespace mesos {
+namespace internal {
+namespace tests {
+
+
+TEST(AgentCallValidationTest, LaunchNestedContainer)
+{
+  // Missing `launch_nested_container`.
+  agent::Call call;
+  call.set_type(agent::Call::LAUNCH_NESTED_CONTAINER);
+
+  Option<Error> error = validation::agent::call::validate(call);
+  EXPECT_SOME(error);
+
+  // `container_id` is not a valid RFC-4122 Version 4 UUID.
+  ContainerID badContainerId;
+  badContainerId.set_value("not-a-uuid");
+
+  agent::Call::LaunchNestedContainer* launch =
+    call.mutable_launch_nested_container();
+
+  launch->mutable_container_id()->CopyFrom(badContainerId);
+
+  error = validation::agent::call::validate(call);
+  EXPECT_SOME(error);
+
+  // Valid `container_id` but missing `container_id.parent`.
+  ContainerID containerId;
+  containerId.set_value(UUID::random().toString());
+
+  launch->mutable_container_id()->CopyFrom(containerId);
+
+  error = validation::agent::call::validate(call);
+  EXPECT_SOME(error);
+
+  // Test the valid case.
+  ContainerID parentContainerId;
+  parentContainerId.set_value(UUID::random().toString());
+
+  
launch->mutable_container_id()->mutable_parent()->CopyFrom(parentContainerId);
+
+  error = validation::agent::call::validate(call);
+  EXPECT_NONE(error);
+
+  // Not expecting a `container_id.parent.parent`.
+  ContainerID grandparentContainerId;
+  grandparentContainerId.set_value(UUID::random().toString());
+
+  launch->mutable_container_id()->mutable_parent()->mutable_parent()
+    ->CopyFrom(grandparentContainerId);
+
+  error = validation::agent::call::validate(call);
+  EXPECT_SOME(error);
+}
+
+
+TEST(AgentCallValidationTest, WaitNestedContainer)
+{
+  // Missing `wait_nested_container`.
+  agent::Call call;
+  call.set_type(agent::Call::WAIT_NESTED_CONTAINER);
+
+  Option<Error> error = validation::agent::call::validate(call);
+  EXPECT_SOME(error);
+
+  // Test the valid case.
+  ContainerID containerId;
+  containerId.set_value(UUID::random().toString());
+
+  agent::Call::WaitNestedContainer* wait =
+    call.mutable_wait_nested_container();
+
+  wait->mutable_container_id()->CopyFrom(containerId);
+
+  error = validation::agent::call::validate(call);
+  EXPECT_NONE(error);
+
+  // Not expecting a `container_id.parent`.
+  ContainerID parentContainerId;
+  parentContainerId.set_value(UUID::random().toString());
+
+  wait->mutable_container_id()->mutable_parent()->CopyFrom(containerId);
+
+  error = validation::agent::call::validate(call);
+  EXPECT_SOME(error);
+}
+
+
+TEST(AgentCallValidationTest, KillNestedContainer)
+{
+  // Missing `kill_nested_container`.
+  agent::Call call;
+  call.set_type(agent::Call::KILL_NESTED_CONTAINER);
+
+  Option<Error> error = validation::agent::call::validate(call);
+  EXPECT_SOME(error);
+
+  // Test the valid case.
+  ContainerID containerId;
+  containerId.set_value(UUID::random().toString());
+
+  agent::Call::KillNestedContainer* kill =
+    call.mutable_kill_nested_container();
+
+  kill->mutable_container_id()->CopyFrom(containerId);
+
+  error = validation::agent::call::validate(call);
+  EXPECT_NONE(error);
+
+  // Not expecting a `container_id.parent`.
+  ContainerID parentContainerId;
+  parentContainerId.set_value(UUID::random().toString());
+
+  kill->mutable_container_id()->mutable_parent()->CopyFrom(containerId);
+
+  error = validation::agent::call::validate(call);
+  EXPECT_SOME(error);
+}
+
+} // namespace tests {
+} // namespace internal {
+} // namespace mesos {

Reply via email to