diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5133550561a..920f9755381 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -193,6 +193,7 @@ if (NOT WIN32) slave/containerizer/mesos/isolators/docker/volume/paths.cpp slave/containerizer/mesos/isolators/network/cni/paths.cpp slave/containerizer/mesos/isolators/network/cni/spec.cpp + slave/containerizer/mesos/isolators/network/cni/utils.cpp slave/containerizer/mesos/isolators/posix/disk.cpp slave/containerizer/mesos/isolators/posix/rlimits.cpp slave/containerizer/mesos/isolators/volume/sandbox_path.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 22506f2b0e2..e79de187e8d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1250,6 +1250,8 @@ libmesos_no_3rdparty_la_SOURCES += \ slave/containerizer/mesos/isolators/network/cni/paths.hpp \ slave/containerizer/mesos/isolators/network/cni/spec.cpp \ slave/containerizer/mesos/isolators/network/cni/spec.hpp \ + slave/containerizer/mesos/isolators/network/cni/utils.cpp \ + slave/containerizer/mesos/isolators/network/cni/utils.hpp \ slave/containerizer/mesos/isolators/posix.hpp \ slave/containerizer/mesos/isolators/posix/disk.cpp \ slave/containerizer/mesos/isolators/posix/disk.hpp \ @@ -1448,7 +1450,7 @@ MESOS_LINUX_FILES = \ slave/containerizer/mesos/isolators/namespaces/ipc.hpp \ slave/containerizer/mesos/isolators/namespaces/pid.cpp \ slave/containerizer/mesos/isolators/namespaces/pid.hpp \ - slave/containerizer/mesos/isolators/network/cni/cni.cpp \ + slave/containerizer/mesos/isolators/network/cni/cni.cpp \ slave/containerizer/mesos/isolators/network/cni/cni.hpp \ slave/containerizer/mesos/isolators/network/cni/plugins/port_mapper/port_mapper.cpp \ slave/containerizer/mesos/isolators/network/cni/plugins/port_mapper/port_mapper.hpp \ diff --git a/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp b/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp index 4142160857d..db479023e74 100644 --- a/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp +++ b/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp @@ -15,6 +15,7 @@ // limitations under the License. #include "slave/containerizer/mesos/isolators/network/cni/cni.hpp" +#include "slave/containerizer/mesos/isolators/network/cni/utils.hpp" #include #include @@ -1271,6 +1272,9 @@ Future NetworkCniIsolatorProcess::attach( CHECK_SOME(containerNetwork.networkInfo); mesos::NetworkInfo networkInfo = containerNetwork.networkInfo.get(); + // Ensure that labels are no longer than 63 characters + compressLongLabels(network_info.mutable_labels()); + JSON::Object mesos; mesos.values["network_info"] = JSON::protobuf(networkInfo); args.values["org.apache.mesos"] = mesos; diff --git a/src/slave/containerizer/mesos/isolators/network/cni/utils.cpp b/src/slave/containerizer/mesos/isolators/network/cni/utils.cpp new file mode 100644 index 00000000000..fa0b1e754df --- /dev/null +++ b/src/slave/containerizer/mesos/isolators/network/cni/utils.cpp @@ -0,0 +1,55 @@ +// 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 + +#include +#include + +#include "slave/containerizer/mesos/isolators/network/cni/utils.hpp" + +void compressLongLabels(mesos::Labels * labels) +{ + MD5_CTX ctx; + unsigned char md5[16]; + char short_label[64]; + + for (int i = 0; i < labels->labels().size(); i++) { + mesos::Label * label = labels->mutable_labels(i); + if (label->has_value()) { + const std::string & value = label->value(); + if (value.length() > 63) { + const char * value_str = value.c_str(); + + // Compute the MD5 sum of the string + _sasl_MD5Init(&ctx); + _sasl_MD5Update(&ctx, (const unsigned char *)value_str, value.length()); + _sasl_MD5Final(md5, &ctx); + + // Keep the first 7 characters of the MD5 sum and the last 55 characters + // of the label, concatenating them with a tilde (63 chars in total) + size_t ofs = value.length() - 55; + snprintf(short_label, 64, "%02x%02x%02x%02x%02x%02x%02x~%s", + md5[0], md5[1], md5[2], md5[3], md5[4], md5[5], md5[6], + &value_str[ofs] + ); + + // Replace label + label->set_value(short_label, 63); + } + } + } +} diff --git a/src/slave/containerizer/mesos/isolators/network/cni/utils.hpp b/src/slave/containerizer/mesos/isolators/network/cni/utils.hpp new file mode 100644 index 00000000000..8afdd8381df --- /dev/null +++ b/src/slave/containerizer/mesos/isolators/network/cni/utils.hpp @@ -0,0 +1,37 @@ +// 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. + +#ifndef __ISOLATOR_CNI_UTIL_HPP__ +#define __ISOLATOR_CNI_UTIL_HPP__ + +#include + +namespace mesos { +namespace internal { +namespace slave { + + +// Ensures that the labels in the `NetworkInfo` are not longer than the maximum +// enforced by the k8s apimachinery validation, that's implicitly used by +// various plugins implementing the CNI interfac: +// https://github.com/kubernetes/kubernetes/blob/132d2af/staging/src/k8s.io/apimachinery/pkg/util/validation/validation.go#L154 +void compressLongLabels(mesos::Labels * labels); + +} // namespace slave { +} // namespace internal { +} // namespace mesos { + +#endif // __ISOLATOR_CNI_SPEC_HPP__