You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by qi...@apache.org on 2017/03/28 09:24:28 UTC
[1/3] mesos git commit: Updated OCI protobuf messages with latest OCI
image spec.
Repository: mesos
Updated Branches:
refs/heads/master 52dfc2f00 -> 18f6642e2
Updated OCI protobuf messages with latest OCI image spec.
Review: https://reviews.apache.org/r/56851/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/87ca2fb0
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/87ca2fb0
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/87ca2fb0
Branch: refs/heads/master
Commit: 87ca2fb0c9d179616a6c1b70882edac783bca34b
Parents: 52dfc2f
Author: Qian Zhang <zh...@gmail.com>
Authored: Tue Mar 28 16:50:03 2017 +0800
Committer: Qian Zhang <zh...@gmail.com>
Committed: Tue Mar 28 16:50:03 2017 +0800
----------------------------------------------------------------------
include/mesos/oci/spec.proto | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/87ca2fb0/include/mesos/oci/spec.proto
----------------------------------------------------------------------
diff --git a/include/mesos/oci/spec.proto b/include/mesos/oci/spec.proto
index 97f3cf3..f7f1979 100644
--- a/include/mesos/oci/spec.proto
+++ b/include/mesos/oci/spec.proto
@@ -29,6 +29,11 @@ message Descriptor {
required string digest = 2;
required int64 size = 3;
repeated string urls = 4;
+
+ // NOTE: We cannot use 'annotations' here because otherwise,
+ // json->protobuf parsing will fail. 'Annotations' is manually
+ // set during parsing.
+ repeated Label Annotations = 5;
}
@@ -50,8 +55,13 @@ message ManifestDescriptor {
required string mediaType = 1;
required string digest = 2;
required int64 size = 3;
- required Platform platform = 4;
+ optional Platform platform = 4;
repeated string urls = 5;
+
+ // NOTE: We cannot use 'annotations' here because otherwise,
+ // json->protobuf parsing will fail. 'Annotations' is manually
+ // set during parsing.
+ repeated Label Annotations = 6;
}
@@ -65,13 +75,13 @@ message Label {
/**
- * Protobuf for the OCI image manifest list JSON schema:
- * https://github.com/opencontainers/image-spec/blob/master/manifest-list.md
+ * Protobuf for the OCI image index JSON schema:
+ * https://github.com/opencontainers/image-spec/blob/master/image-index.md
*
* The OCI MIME type of this message is:
- * application/vnd.oci.image.manifest.list.v1+json
+ * application/vnd.oci.image.index.v1+json
*/
-message ManifestList {
+message Index {
required int64 schemaVersion = 1;
repeated ManifestDescriptor manifests = 2;
[2/3] mesos git commit: Updated OCI spec parsing & validation code
with latest OCI image spec.
Posted by qi...@apache.org.
Updated OCI spec parsing & validation code with latest OCI image spec.
Review: https://reviews.apache.org/r/56852/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/0c1d50d2
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/0c1d50d2
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/0c1d50d2
Branch: refs/heads/master
Commit: 0c1d50d236dbc100b9cbab194daba409483eed7a
Parents: 87ca2fb
Author: Qian Zhang <zh...@gmail.com>
Authored: Tue Mar 28 16:50:11 2017 +0800
Committer: Qian Zhang <zh...@gmail.com>
Committed: Tue Mar 28 16:50:11 2017 +0800
----------------------------------------------------------------------
include/mesos/oci/spec.hpp | 15 +++-
src/oci/spec.cpp | 152 +++++++++++++++++++++++++++-------------
2 files changed, 116 insertions(+), 51 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/0c1d50d2/include/mesos/oci/spec.hpp
----------------------------------------------------------------------
diff --git a/include/mesos/oci/spec.hpp b/include/mesos/oci/spec.hpp
index ea4f29e..d8eef84 100644
--- a/include/mesos/oci/spec.hpp
+++ b/include/mesos/oci/spec.hpp
@@ -26,8 +26,8 @@ namespace v1 {
// Constant strings for OCI image media types:
// https://github.com/opencontainers/image-spec/blob/master/media-types.md
-constexpr char MEDIA_TYPE_MANIFEST_LIST[] =
- "application/vnd.oci.image.manifest.list.v1+json";
+constexpr char MEDIA_TYPE_INDEX[] =
+ "application/vnd.oci.image.index.v1+json";
constexpr char MEDIA_TYPE_MANIFEST[] =
"application/vnd.oci.image.manifest.v1+json";
@@ -36,13 +36,22 @@ constexpr char MEDIA_TYPE_CONFIG[] =
"application/vnd.oci.image.config.v1+json";
constexpr char MEDIA_TYPE_LAYER[] =
+ "application/vnd.oci.image.layer.v1.tar";
+
+constexpr char MEDIA_TYPE_LAYER_GZIP[] =
"application/vnd.oci.image.layer.v1.tar+gzip";
constexpr char MEDIA_TYPE_NONDIST_LAYER[] =
+ "application/vnd.oci.image.layer.nondistributable.v1.tar";
+
+constexpr char MEDIA_TYPE_NONDIST_LAYER_GZIP[] =
"application/vnd.oci.image.layer.nondistributable.v1.tar+gzip";
+// Rootfs type of OCI image configuration.
+constexpr char ROOTFS_TYPE[] = "layers";
+
/**
- * Returns the OCI v1 descriptor, image manifest list, image manifest
+ * Returns the OCI v1 descriptor, image index, image manifest
* and image configuration from the given string.
*/
template <typename T>
http://git-wip-us.apache.org/repos/asf/mesos/blob/0c1d50d2/src/oci/spec.cpp
----------------------------------------------------------------------
diff --git a/src/oci/spec.cpp b/src/oci/spec.cpp
index 0a88edb..06fceb4 100644
--- a/src/oci/spec.cpp
+++ b/src/oci/spec.cpp
@@ -43,25 +43,20 @@ Option<Error> validateDigest(const string& digest)
}
-Option<Error> validate(const ManifestList& manifestList)
+Option<Error> validate(const Index& index)
{
- if (manifestList.schemaversion() != 2) {
+ if (index.schemaversion() != 2) {
return Error(
"Incorrect 'schemaVersion': " +
- stringify(manifestList.schemaversion()));
+ stringify(index.schemaversion()));
}
- foreach (const ManifestDescriptor& manifest, manifestList.manifests()) {
+ foreach (const ManifestDescriptor& manifest, index.manifests()) {
Option<Error> error = validateDigest(manifest.digest());
if (error.isSome()) {
return Error(
"Failed to validate 'digest' of the 'manifest': " + error->message);
}
-
- if (manifest.mediatype() != MEDIA_TYPE_MANIFEST) {
- return Error(
- "Incorrect 'mediaType' of the 'manifest': " + manifest.mediatype());
- }
}
return None();
@@ -101,7 +96,9 @@ Option<Error> validate(const Manifest& manifest)
}
if (layer.mediatype() != MEDIA_TYPE_LAYER &&
- layer.mediatype() != MEDIA_TYPE_NONDIST_LAYER) {
+ layer.mediatype() != MEDIA_TYPE_LAYER_GZIP &&
+ layer.mediatype() != MEDIA_TYPE_NONDIST_LAYER &&
+ layer.mediatype() != MEDIA_TYPE_NONDIST_LAYER_GZIP) {
return Error(
"Incorrect 'mediaType' of the 'layer': " + layer.mediatype());
}
@@ -110,6 +107,16 @@ Option<Error> validate(const Manifest& manifest)
return None();
}
+
+Option<Error> validate(const Configuration& configuration)
+{
+ if (configuration.rootfs().type() != ROOTFS_TYPE) {
+ return Error("Incorrect 'type': " + configuration.rootfs().type());
+ }
+
+ return None();
+}
+
} // namespace internal {
@@ -126,6 +133,28 @@ Try<Descriptor> parse(const string& s)
return Error("Protobuf parse failed: " + descriptor.error());
}
+ // Manually parse 'annotations' field.
+ Result<JSON::Value> annotations = json->find<JSON::Value>("annotations");
+ if (annotations.isError()) {
+ return Error(
+ "Failed to find 'annotations': " + annotations.error());
+ }
+
+ if (annotations.isSome() && !annotations->is<JSON::Null>()) {
+ foreachpair (const string& key,
+ const JSON::Value& value,
+ annotations->as<JSON::Object>().values) {
+ if (!value.is<JSON::String>()) {
+ return Error(
+ "The value of annotation key '" + key + "' is not a JSON string");
+ }
+
+ Label* annotation = descriptor->add_annotations();
+ annotation->set_key(key);
+ annotation->set_value(value.as<JSON::String>().value);
+ }
+ }
+
Option<Error> error = internal::validateDigest(descriptor->digest());
if (error.isSome()) {
return Error(
@@ -137,20 +166,20 @@ Try<Descriptor> parse(const string& s)
template <>
-Try<ManifestList> parse(const string& s)
+Try<Index> parse(const string& s)
{
Try<JSON::Object> json = JSON::parse<JSON::Object>(s);
if (json.isError()) {
return Error("JSON parse failed: " + json.error());
}
- Try<ManifestList> manifestList = protobuf::parse<ManifestList>(json.get());
- if (manifestList.isError()) {
- return Error("Protobuf parse failed: " + manifestList.error());
+ Try<Index> index = protobuf::parse<Index>(json.get());
+ if (index.isError()) {
+ return Error("Protobuf parse failed: " + index.error());
}
- // Manually parse 'manifest.platform.os.version' and
- // 'manifest.platform.os.features'.
+ // Manually parse 'manifest.annotations', 'manifest.platform.os.version'
+ // and 'manifest.platform.os.features'.
Result<JSON::Array> manifests = json->at<JSON::Array>("manifests");
if (manifests.isError()) {
return Error("Failed to find 'manifests': " + manifests.error());
@@ -172,9 +201,9 @@ Try<ManifestList> parse(const string& s)
}
ManifestDescriptor* _manifest = nullptr;
- for (int i = 0; i < manifestList->manifests_size(); i++) {
- if (manifestList->manifests(i).digest() == digest.get()) {
- _manifest = manifestList->mutable_manifests(i);
+ for (int i = 0; i < index->manifests_size(); i++) {
+ if (index->manifests(i).digest() == digest.get()) {
+ _manifest = index->mutable_manifests(i);
break;
}
}
@@ -185,40 +214,61 @@ Try<ManifestList> parse(const string& s)
digest->value + "'");
}
- Result<JSON::Object> platform = manifest.at<JSON::Object>("platform");
- if (platform.isError()) {
- return Error("Failed to find 'platform': " + platform.error());
- } else if (platform.isNone()) {
- return Error("Unable to find 'platform'");
- }
-
- Result<JSON::String> osVersion = platform->at<JSON::String>("os.version");
- if (osVersion.isError()) {
+ Result<JSON::Value> annotations = manifest.find<JSON::Value>("annotations");
+ if (annotations.isError()) {
return Error(
- "Failed to find 'platform.os.version': " + osVersion.error());
+ "Failed to find 'annotations': " + annotations.error());
}
- if (osVersion.isSome()) {
- Platform* platform = _manifest->mutable_platform();
- platform->set_os_version(osVersion->value);
+ if (annotations.isSome() && !annotations->is<JSON::Null>()) {
+ foreachpair (const string& key,
+ const JSON::Value& value,
+ annotations->as<JSON::Object>().values) {
+ if (!value.is<JSON::String>()) {
+ return Error(
+ "The value of annotation key '" + key + "' is not a JSON string");
+ }
+
+ Label* annotation = _manifest->add_annotations();
+ annotation->set_key(key);
+ annotation->set_value(value.as<JSON::String>().value);
+ }
}
- Result<JSON::Array> osFeatures = platform->at<JSON::Array>("os.features");
- if (osFeatures.isError()) {
- return Error(
- "Failed to find 'platform.os.features': " + osFeatures.error());
+ Result<JSON::Object> platform = manifest.at<JSON::Object>("platform");
+ if (platform.isError()) {
+ return Error("Failed to find 'platform': " + platform.error());
}
- if (osFeatures.isSome()) {
- const vector<JSON::Value>& values = osFeatures->values;
- if (values.size() != 0) {
+ if (platform.isSome()) {
+ Result<JSON::String> osVersion = platform->at<JSON::String>("os.version");
+ if (osVersion.isError()) {
+ return Error(
+ "Failed to find 'platform.os.version': " + osVersion.error());
+ }
+
+ if (osVersion.isSome()) {
Platform* platform = _manifest->mutable_platform();
- foreach (const JSON::Value& value, values) {
- if (!value.is<JSON::String>()) {
- return Error("Expecting OS feature to be string type");
- }
+ platform->set_os_version(osVersion->value);
+ }
- platform->add_os_features(value.as<JSON::String>().value);
+ Result<JSON::Array> osFeatures = platform->at<JSON::Array>("os.features");
+ if (osFeatures.isError()) {
+ return Error(
+ "Failed to find 'platform.os.features': " + osFeatures.error());
+ }
+
+ if (osFeatures.isSome()) {
+ const vector<JSON::Value>& values = osFeatures->values;
+ if (values.size() != 0) {
+ Platform* platform = _manifest->mutable_platform();
+ foreach (const JSON::Value& value, values) {
+ if (!value.is<JSON::String>()) {
+ return Error("Expecting OS feature to be string type");
+ }
+
+ platform->add_os_features(value.as<JSON::String>().value);
+ }
}
}
}
@@ -240,19 +290,19 @@ Try<ManifestList> parse(const string& s)
"The value of annotation key '" + key + "' is not a JSON string");
}
- Label* annotation = manifestList->add_annotations();
+ Label* annotation = index->add_annotations();
annotation->set_key(key);
annotation->set_value(value.as<JSON::String>().value);
}
}
- Option<Error> error = internal::validate(manifestList.get());
+ Option<Error> error = internal::validate(index.get());
if (error.isSome()) {
return Error(
- "OCI v1 image manifest list validation failed: " + error->message);
+ "OCI v1 image index validation failed: " + error->message);
}
- return manifestList.get();
+ return index.get();
}
@@ -368,6 +418,12 @@ Try<Configuration> parse(const string& s)
}
}
+ Option<Error> error = internal::validate(configuration.get());
+ if (error.isSome()) {
+ return Error(
+ "OCI v1 image configuration validation failed: " + error->message);
+ }
+
return configuration.get();
}
[3/3] mesos git commit: Update OCI tests with the latest OCI image
spec.
Posted by qi...@apache.org.
Update OCI tests with the latest OCI image spec.
Review: https://reviews.apache.org/r/56853/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/18f6642e
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/18f6642e
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/18f6642e
Branch: refs/heads/master
Commit: 18f6642e28d0fee1031a88e62265a49e3bd601a6
Parents: 0c1d50d
Author: Qian Zhang <zh...@gmail.com>
Authored: Tue Mar 28 16:50:18 2017 +0800
Committer: Qian Zhang <zh...@gmail.com>
Committed: Tue Mar 28 16:50:18 2017 +0800
----------------------------------------------------------------------
src/tests/containerizer/oci_spec_tests.cpp | 32 ++++++++++++-------------
1 file changed, 16 insertions(+), 16 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/18f6642e/src/tests/containerizer/oci_spec_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/oci_spec_tests.cpp b/src/tests/containerizer/oci_spec_tests.cpp
index 29a8f23..011e6d0 100644
--- a/src/tests/containerizer/oci_spec_tests.cpp
+++ b/src/tests/containerizer/oci_spec_tests.cpp
@@ -68,7 +68,7 @@ TEST_F(OCISpecTest, ParseDescriptor)
}
-TEST_F(OCISpecTest, ParseManifestList)
+TEST_F(OCISpecTest, ParseIndex)
{
const string json =
R"~(
@@ -104,54 +104,54 @@ TEST_F(OCISpecTest, ParseManifestList)
}
})~";
- Try<image::v1::ManifestList> manifestList =
- image::v1::parse<image::v1::ManifestList>(json);
+ Try<image::v1::Index> index =
+ image::v1::parse<image::v1::Index>(json);
- ASSERT_SOME(manifestList);
+ ASSERT_SOME(index);
- EXPECT_EQ(2u, manifestList->schemaversion());
+ EXPECT_EQ(2u, index->schemaversion());
EXPECT_EQ(
"application/vnd.oci.image.manifest.v1+json",
- manifestList->manifests(0).mediatype());
+ index->manifests(0).mediatype());
- EXPECT_EQ(7143u, manifestList->manifests(0).size());
+ EXPECT_EQ(7143u, index->manifests(0).size());
EXPECT_EQ(
"sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f",
- manifestList->manifests(0).digest());
+ index->manifests(0).digest());
EXPECT_EQ(
"ppc64le",
- manifestList->manifests(0).platform().architecture());
+ index->manifests(0).platform().architecture());
EXPECT_EQ(
"linux",
- manifestList->manifests(0).platform().os());
+ index->manifests(0).platform().os());
EXPECT_EQ(
"16.04",
- manifestList->manifests(0).platform().os_version());
+ index->manifests(0).platform().os_version());
EXPECT_EQ(
"sse4",
- manifestList->manifests(1).platform().os_features(0));
+ index->manifests(1).platform().os_features(0));
EXPECT_EQ(
"com.example.key1",
- manifestList->annotations(0).key());
+ index->annotations(0).key());
EXPECT_EQ(
"value1",
- manifestList->annotations(0).value());
+ index->annotations(0).value());
EXPECT_EQ(
"com.example.key2",
- manifestList->annotations(1).key());
+ index->annotations(1).key());
EXPECT_EQ(
"value2",
- manifestList->annotations(1).value());
+ index->annotations(1).value());
}