Update go dependencies

This commit is contained in:
Manuel de Brito Fontes 2017-11-12 14:14:23 -03:00
parent a858c549d9
commit f3bde94d68
643 changed files with 14296 additions and 19354 deletions

View file

@ -1,13 +0,0 @@
{
"Rules": [
{
"SelectorRegexp": "k8s[.]io/kubernetes",
"AllowedPrefixes": [
""
],
"ForbiddenPrefixes": [
"k8s.io/kubernetes/cmd"
]
}
]
}

View file

@ -15,7 +15,6 @@ go_library(
"types.go",
"zz_generated.deepcopy.go",
],
importpath = "k8s.io/kubernetes/pkg/api",
visibility = ["//visibility:public"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
@ -37,10 +36,53 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["taint_test.go"],
importpath = "k8s.io/kubernetes/pkg/api",
library = ":go_default_library",
)
go_test(
name = "go_default_xtest",
srcs = [
"conversion_test.go",
"copy_test.go",
"deep_copy_test.go",
"defaulting_test.go",
"meta_test.go",
"serialization_proto_test.go",
"serialization_test.go",
"unstructured_test.go",
],
deps = [
":go_default_library",
"//pkg/api/testapi:go_default_library",
"//pkg/api/testing:go_default_library",
"//pkg/api/v1:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/apis/extensions/v1beta1:go_default_library",
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
"//vendor/github.com/golang/protobuf/proto:go_default_library",
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/github.com/json-iterator/go:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/streaming:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
@ -65,6 +107,7 @@ filegroup(
"//pkg/api/testapi:all-srcs",
"//pkg/api/testing:all-srcs",
"//pkg/api/unversioned:all-srcs",
"//pkg/api/util:all-srcs",
"//pkg/api/v1:all-srcs",
"//pkg/api/validation:all-srcs",
],

117
vendor/k8s.io/kubernetes/pkg/api/conversion_test.go generated vendored Normal file
View file

@ -0,0 +1,117 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed 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.
*/
package api_test
import (
"io/ioutil"
"math/rand"
"testing"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi"
kapitesting "k8s.io/kubernetes/pkg/api/testing"
)
func BenchmarkPodConversion(b *testing.B) {
apiObjectFuzzer := fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(benchmarkSeed), api.Codecs)
items := make([]api.Pod, 4)
for i := range items {
apiObjectFuzzer.Fuzz(&items[i])
items[i].Spec.InitContainers = nil
items[i].Status.InitContainerStatuses = nil
}
// add a fixed item
items = append(items, benchmarkPod)
width := len(items)
scheme := api.Scheme
for i := 0; i < b.N; i++ {
pod := &items[i%width]
versionedObj, err := scheme.UnsafeConvertToVersion(pod, api.Registry.GroupOrDie(api.GroupName).GroupVersion)
if err != nil {
b.Fatalf("Conversion error: %v", err)
}
if _, err = scheme.UnsafeConvertToVersion(versionedObj, testapi.Default.InternalGroupVersion()); err != nil {
b.Fatalf("Conversion error: %v", err)
}
}
}
func BenchmarkNodeConversion(b *testing.B) {
data, err := ioutil.ReadFile("node_example.json")
if err != nil {
b.Fatalf("Unexpected error while reading file: %v", err)
}
var node api.Node
if err := runtime.DecodeInto(testapi.Default.Codec(), data, &node); err != nil {
b.Fatalf("Unexpected error decoding node: %v", err)
}
scheme := api.Scheme
var result *api.Node
b.ResetTimer()
for i := 0; i < b.N; i++ {
versionedObj, err := scheme.UnsafeConvertToVersion(&node, api.Registry.GroupOrDie(api.GroupName).GroupVersion)
if err != nil {
b.Fatalf("Conversion error: %v", err)
}
obj, err := scheme.UnsafeConvertToVersion(versionedObj, testapi.Default.InternalGroupVersion())
if err != nil {
b.Fatalf("Conversion error: %v", err)
}
result = obj.(*api.Node)
}
b.StopTimer()
if !apiequality.Semantic.DeepDerivative(node, *result) {
b.Fatalf("Incorrect conversion: %s", diff.ObjectDiff(node, *result))
}
}
func BenchmarkReplicationControllerConversion(b *testing.B) {
data, err := ioutil.ReadFile("replication_controller_example.json")
if err != nil {
b.Fatalf("Unexpected error while reading file: %v", err)
}
var replicationController api.ReplicationController
if err := runtime.DecodeInto(testapi.Default.Codec(), data, &replicationController); err != nil {
b.Fatalf("Unexpected error decoding node: %v", err)
}
scheme := api.Scheme
var result *api.ReplicationController
b.ResetTimer()
for i := 0; i < b.N; i++ {
versionedObj, err := scheme.UnsafeConvertToVersion(&replicationController, api.Registry.GroupOrDie(api.GroupName).GroupVersion)
if err != nil {
b.Fatalf("Conversion error: %v", err)
}
obj, err := scheme.UnsafeConvertToVersion(versionedObj, testapi.Default.InternalGroupVersion())
if err != nil {
b.Fatalf("Conversion error: %v", err)
}
result = obj.(*api.ReplicationController)
}
b.StopTimer()
if !apiequality.Semantic.DeepDerivative(replicationController, *result) {
b.Fatalf("Incorrect conversion: expected %v, got %v", replicationController, *result)
}
}

87
vendor/k8s.io/kubernetes/pkg/api/copy_test.go generated vendored Normal file
View file

@ -0,0 +1,87 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed 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.
*/
package api_test
import (
"bytes"
"math/rand"
"reflect"
"testing"
"github.com/google/gofuzz"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
"k8s.io/apimachinery/pkg/api/testing/roundtrip"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi"
kapitesting "k8s.io/kubernetes/pkg/api/testing"
)
func TestDeepCopyApiObjects(t *testing.T) {
for i := 0; i < *roundtrip.FuzzIters; i++ {
for _, version := range []schema.GroupVersion{testapi.Default.InternalGroupVersion(), api.Registry.GroupOrDie(api.GroupName).GroupVersion} {
f := fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(rand.Int63()), api.Codecs)
for kind := range api.Scheme.KnownTypes(version) {
doDeepCopyTest(t, version.WithKind(kind), f)
}
}
}
}
func doDeepCopyTest(t *testing.T, kind schema.GroupVersionKind, f *fuzz.Fuzzer) {
item, err := api.Scheme.New(kind)
if err != nil {
t.Fatalf("Could not create a %v: %s", kind, err)
}
f.Fuzz(item)
itemCopy := item.DeepCopyObject()
if !reflect.DeepEqual(item, itemCopy) {
t.Errorf("\nexpected: %#v\n\ngot: %#v\n\ndiff: %v", item, itemCopy, diff.ObjectReflectDiff(item, itemCopy))
}
prefuzzData := &bytes.Buffer{}
if err := api.Codecs.LegacyCodec(kind.GroupVersion()).Encode(item, prefuzzData); err != nil {
t.Errorf("Could not encode a %v: %s", kind, err)
return
}
// Refuzz the copy, which should have no effect on the original
f.Fuzz(itemCopy)
postfuzzData := &bytes.Buffer{}
if err := api.Codecs.LegacyCodec(kind.GroupVersion()).Encode(item, postfuzzData); err != nil {
t.Errorf("Could not encode a %v: %s", kind, err)
return
}
if bytes.Compare(prefuzzData.Bytes(), postfuzzData.Bytes()) != 0 {
t.Log(diff.StringDiff(prefuzzData.String(), postfuzzData.String()))
t.Errorf("Fuzzing copy modified original of %#v", kind)
return
}
}
func TestDeepCopySingleType(t *testing.T) {
for i := 0; i < *roundtrip.FuzzIters; i++ {
for _, version := range []schema.GroupVersion{testapi.Default.InternalGroupVersion(), api.Registry.GroupOrDie(api.GroupName).GroupVersion} {
f := fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(rand.Int63()), api.Codecs)
doDeepCopyTest(t, version.WithKind("Pod"), f)
}
}
}

177
vendor/k8s.io/kubernetes/pkg/api/deep_copy_test.go generated vendored Normal file
View file

@ -0,0 +1,177 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed 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.
*/
package api_test
import (
"io/ioutil"
"testing"
"time"
apiequality "k8s.io/apimachinery/pkg/api/equality"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi"
)
func parseTimeOrDie(ts string) metav1.Time {
t, err := time.Parse(time.RFC3339, ts)
if err != nil {
panic(err)
}
return metav1.Time{Time: t}
}
var benchmarkPod api.Pod = api.Pod{
TypeMeta: metav1.TypeMeta{
Kind: "Pod",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "etcd-server-e2e-test-wojtekt-master",
Namespace: "default",
SelfLink: "/api/v1/namespaces/default/pods/etcd-server-e2e-test-wojtekt-master",
UID: types.UID("a671734a-e8e5-11e4-8fde-42010af09327"),
ResourceVersion: "22",
CreationTimestamp: parseTimeOrDie("2015-04-22T11:49:36Z"),
},
Spec: api.PodSpec{
Volumes: []api.Volume{
{
Name: "varetcd",
VolumeSource: api.VolumeSource{
HostPath: &api.HostPathVolumeSource{
Path: "/mnt/master-pd/var/etcd",
},
},
},
},
Containers: []api.Container{
{
Name: "etcd-container",
Image: "gcr.io/google_containers/etcd:2.0.9",
Command: []string{
"/usr/local/bin/etcd",
"--addr",
"127.0.0.1:2379",
"--bind-addr",
"127.0.0.1:2379",
"--data-dir",
"/var/etcd/data",
},
Ports: []api.ContainerPort{
{
Name: "serverport",
HostPort: 2380,
ContainerPort: 2380,
Protocol: "TCP",
},
{
Name: "clientport",
HostPort: 2379,
ContainerPort: 2379,
Protocol: "TCP",
},
},
VolumeMounts: []api.VolumeMount{
{
Name: "varetcd",
MountPath: "/var/etcd",
},
},
TerminationMessagePath: "/dev/termination-log",
ImagePullPolicy: api.PullIfNotPresent,
},
},
RestartPolicy: api.RestartPolicyAlways,
DNSPolicy: api.DNSClusterFirst,
NodeName: "e2e-test-wojtekt-master",
},
Status: api.PodStatus{
Phase: api.PodRunning,
Conditions: []api.PodCondition{
{
Type: api.PodReady,
Status: api.ConditionTrue,
},
},
ContainerStatuses: []api.ContainerStatus{
{
Name: "etcd-container",
State: api.ContainerState{
Running: &api.ContainerStateRunning{
StartedAt: parseTimeOrDie("2015-04-22T11:49:32Z"),
},
},
Ready: true,
RestartCount: 0,
Image: "gcr.io/google_containers/etcd:2.0.9",
ImageID: "docker://b6b9a86dc06aa1361357ca1b105feba961f6a4145adca6c54e142c0be0fe87b0",
ContainerID: "docker://3cbbf818f1addfc252957b4504f56ef2907a313fe6afc47fc75373674255d46d",
},
},
},
}
func BenchmarkPodCopy(b *testing.B) {
var result *api.Pod
for i := 0; i < b.N; i++ {
result = benchmarkPod.DeepCopy()
}
if !apiequality.Semantic.DeepEqual(benchmarkPod, *result) {
b.Fatalf("Incorrect copy: expected %v, got %v", benchmarkPod, *result)
}
}
func BenchmarkNodeCopy(b *testing.B) {
data, err := ioutil.ReadFile("node_example.json")
if err != nil {
b.Fatalf("Unexpected error while reading file: %v", err)
}
var node api.Node
if err := runtime.DecodeInto(testapi.Default.Codec(), data, &node); err != nil {
b.Fatalf("Unexpected error decoding node: %v", err)
}
var result *api.Node
for i := 0; i < b.N; i++ {
result = node.DeepCopy()
}
if !apiequality.Semantic.DeepEqual(node, *result) {
b.Fatalf("Incorrect copy: expected %v, got %v", node, *result)
}
}
func BenchmarkReplicationControllerCopy(b *testing.B) {
data, err := ioutil.ReadFile("replication_controller_example.json")
if err != nil {
b.Fatalf("Unexpected error while reading file: %v", err)
}
var replicationController api.ReplicationController
if err := runtime.DecodeInto(testapi.Default.Codec(), data, &replicationController); err != nil {
b.Fatalf("Unexpected error decoding node: %v", err)
}
var result *api.ReplicationController
for i := 0; i < b.N; i++ {
result = replicationController.DeepCopy()
}
if !apiequality.Semantic.DeepEqual(replicationController, *result) {
b.Fatalf("Incorrect copy: expected %v, got %v", replicationController, *result)
}
}

225
vendor/k8s.io/kubernetes/pkg/api/defaulting_test.go generated vendored Normal file
View file

@ -0,0 +1,225 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed 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.
*/
package api_test
import (
"math/rand"
"reflect"
"sort"
"testing"
fuzz "github.com/google/gofuzz"
apiv1 "k8s.io/api/core/v1"
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
roundtrip "k8s.io/apimachinery/pkg/api/testing/roundtrip"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/kubernetes/pkg/api"
)
type orderedGroupVersionKinds []schema.GroupVersionKind
func (o orderedGroupVersionKinds) Len() int { return len(o) }
func (o orderedGroupVersionKinds) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
func (o orderedGroupVersionKinds) Less(i, j int) bool {
return o[i].String() < o[j].String()
}
// TODO: add a reflexive test that verifies that all SetDefaults functions are registered
func TestDefaulting(t *testing.T) {
// these are the known types with defaulters - you must add to this list if you add a top level defaulter
typesWithDefaulting := map[schema.GroupVersionKind]struct{}{
{Group: "", Version: "v1", Kind: "ConfigMap"}: {},
{Group: "", Version: "v1", Kind: "ConfigMapList"}: {},
{Group: "", Version: "v1", Kind: "Endpoints"}: {},
{Group: "", Version: "v1", Kind: "EndpointsList"}: {},
{Group: "", Version: "v1", Kind: "Namespace"}: {},
{Group: "", Version: "v1", Kind: "NamespaceList"}: {},
{Group: "", Version: "v1", Kind: "Node"}: {},
{Group: "", Version: "v1", Kind: "NodeList"}: {},
{Group: "", Version: "v1", Kind: "PersistentVolume"}: {},
{Group: "", Version: "v1", Kind: "PersistentVolumeList"}: {},
{Group: "", Version: "v1", Kind: "PersistentVolumeClaim"}: {},
{Group: "", Version: "v1", Kind: "PersistentVolumeClaimList"}: {},
{Group: "", Version: "v1", Kind: "PodAttachOptions"}: {},
{Group: "", Version: "v1", Kind: "PodExecOptions"}: {},
{Group: "", Version: "v1", Kind: "Pod"}: {},
{Group: "", Version: "v1", Kind: "PodList"}: {},
{Group: "", Version: "v1", Kind: "PodTemplate"}: {},
{Group: "", Version: "v1", Kind: "PodTemplateList"}: {},
{Group: "", Version: "v1", Kind: "ReplicationController"}: {},
{Group: "", Version: "v1", Kind: "ReplicationControllerList"}: {},
{Group: "", Version: "v1", Kind: "Secret"}: {},
{Group: "", Version: "v1", Kind: "SecretList"}: {},
{Group: "", Version: "v1", Kind: "Service"}: {},
{Group: "", Version: "v1", Kind: "ServiceList"}: {},
{Group: "apps", Version: "v1beta1", Kind: "StatefulSet"}: {},
{Group: "apps", Version: "v1beta1", Kind: "StatefulSetList"}: {},
{Group: "apps", Version: "v1beta2", Kind: "StatefulSet"}: {},
{Group: "apps", Version: "v1beta2", Kind: "StatefulSetList"}: {},
{Group: "autoscaling", Version: "v1", Kind: "HorizontalPodAutoscaler"}: {},
{Group: "autoscaling", Version: "v1", Kind: "HorizontalPodAutoscalerList"}: {},
{Group: "autoscaling", Version: "v2beta1", Kind: "HorizontalPodAutoscaler"}: {},
{Group: "autoscaling", Version: "v2beta1", Kind: "HorizontalPodAutoscalerList"}: {},
{Group: "batch", Version: "v1", Kind: "Job"}: {},
{Group: "batch", Version: "v1", Kind: "JobList"}: {},
{Group: "batch", Version: "v1beta1", Kind: "CronJob"}: {},
{Group: "batch", Version: "v1beta1", Kind: "CronJobList"}: {},
{Group: "batch", Version: "v1beta1", Kind: "JobTemplate"}: {},
{Group: "batch", Version: "v2alpha1", Kind: "CronJob"}: {},
{Group: "batch", Version: "v2alpha1", Kind: "CronJobList"}: {},
{Group: "batch", Version: "v2alpha1", Kind: "JobTemplate"}: {},
{Group: "certificates.k8s.io", Version: "v1beta1", Kind: "CertificateSigningRequest"}: {},
{Group: "certificates.k8s.io", Version: "v1beta1", Kind: "CertificateSigningRequestList"}: {},
{Group: "componentconfig", Version: "v1alpha1", Kind: "KubeProxyConfiguration"}: {},
{Group: "componentconfig", Version: "v1alpha1", Kind: "KubeSchedulerConfiguration"}: {},
{Group: "componentconfig", Version: "v1alpha1", Kind: "KubeletConfiguration"}: {},
{Group: "kubeadm.k8s.io", Version: "v1alpha1", Kind: "MasterConfiguration"}: {},
// This object contains only int fields which currently breaks the defaulting test because
// it's pretty stupid. Once we add non integer fields, we should uncomment this.
// {Group: "kubeadm.k8s.io", Version: "v1alpha1", Kind: "NodeConfiguration"}: {},
{Group: "extensions", Version: "v1beta1", Kind: "DaemonSet"}: {},
{Group: "extensions", Version: "v1beta1", Kind: "DaemonSetList"}: {},
{Group: "apps", Version: "v1beta2", Kind: "DaemonSet"}: {},
{Group: "apps", Version: "v1beta2", Kind: "DaemonSetList"}: {},
{Group: "extensions", Version: "v1beta1", Kind: "Deployment"}: {},
{Group: "extensions", Version: "v1beta1", Kind: "DeploymentList"}: {},
{Group: "apps", Version: "v1beta1", Kind: "Deployment"}: {},
{Group: "apps", Version: "v1beta1", Kind: "DeploymentList"}: {},
{Group: "apps", Version: "v1beta2", Kind: "Deployment"}: {},
{Group: "apps", Version: "v1beta2", Kind: "DeploymentList"}: {},
{Group: "extensions", Version: "v1beta1", Kind: "PodSecurityPolicy"}: {},
{Group: "extensions", Version: "v1beta1", Kind: "PodSecurityPolicyList"}: {},
{Group: "apps", Version: "v1beta2", Kind: "ReplicaSet"}: {},
{Group: "apps", Version: "v1beta2", Kind: "ReplicaSetList"}: {},
{Group: "extensions", Version: "v1beta1", Kind: "ReplicaSet"}: {},
{Group: "extensions", Version: "v1beta1", Kind: "ReplicaSetList"}: {},
{Group: "extensions", Version: "v1beta1", Kind: "NetworkPolicy"}: {},
{Group: "extensions", Version: "v1beta1", Kind: "NetworkPolicyList"}: {},
{Group: "rbac.authorization.k8s.io", Version: "v1alpha1", Kind: "ClusterRoleBinding"}: {},
{Group: "rbac.authorization.k8s.io", Version: "v1alpha1", Kind: "ClusterRoleBindingList"}: {},
{Group: "rbac.authorization.k8s.io", Version: "v1alpha1", Kind: "RoleBinding"}: {},
{Group: "rbac.authorization.k8s.io", Version: "v1alpha1", Kind: "RoleBindingList"}: {},
{Group: "rbac.authorization.k8s.io", Version: "v1beta1", Kind: "ClusterRoleBinding"}: {},
{Group: "rbac.authorization.k8s.io", Version: "v1beta1", Kind: "ClusterRoleBindingList"}: {},
{Group: "rbac.authorization.k8s.io", Version: "v1beta1", Kind: "RoleBinding"}: {},
{Group: "rbac.authorization.k8s.io", Version: "v1beta1", Kind: "RoleBindingList"}: {},
{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRoleBinding"}: {},
{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRoleBindingList"}: {},
{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "RoleBinding"}: {},
{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "RoleBindingList"}: {},
{Group: "settings.k8s.io", Version: "v1alpha1", Kind: "PodPreset"}: {},
{Group: "settings.k8s.io", Version: "v1alpha1", Kind: "PodPresetList"}: {},
{Group: "admissionregistration.k8s.io", Version: "v1alpha1", Kind: "ExternalAdmissionHookConfiguration"}: {},
{Group: "admissionregistration.k8s.io", Version: "v1alpha1", Kind: "ExternalAdmissionHookConfigurationList"}: {},
{Group: "networking.k8s.io", Version: "v1", Kind: "NetworkPolicy"}: {},
{Group: "networking.k8s.io", Version: "v1", Kind: "NetworkPolicyList"}: {},
{Group: "storage.k8s.io", Version: "v1beta1", Kind: "StorageClass"}: {},
{Group: "storage.k8s.io", Version: "v1beta1", Kind: "StorageClassList"}: {},
{Group: "storage.k8s.io", Version: "v1", Kind: "StorageClass"}: {},
{Group: "storage.k8s.io", Version: "v1", Kind: "StorageClassList"}: {},
}
f := fuzz.New().NilChance(.5).NumElements(1, 1).RandSource(rand.NewSource(1))
f.Funcs(
func(s *runtime.RawExtension, c fuzz.Continue) {},
func(s *metav1.LabelSelector, c fuzz.Continue) {
c.FuzzNoCustom(s)
s.MatchExpressions = nil // need to fuzz this specially
},
func(s *apiv1.ListOptions, c fuzz.Continue) {
c.FuzzNoCustom(s)
s.LabelSelector = "" // need to fuzz requirement strings specially
s.FieldSelector = "" // need to fuzz requirement strings specially
},
func(s *extensionsv1beta1.ScaleStatus, c fuzz.Continue) {
c.FuzzNoCustom(s)
s.TargetSelector = "" // need to fuzz requirement strings specially
},
)
scheme := api.Scheme
var testTypes orderedGroupVersionKinds
for gvk := range scheme.AllKnownTypes() {
if gvk.Version == runtime.APIVersionInternal {
continue
}
testTypes = append(testTypes, gvk)
}
sort.Sort(testTypes)
for _, gvk := range testTypes {
_, expectedChanged := typesWithDefaulting[gvk]
iter := 0
changedOnce := false
for {
if iter > *roundtrip.FuzzIters {
if !expectedChanged || changedOnce {
break
}
if iter > 300 {
t.Errorf("expected %s to trigger defaulting due to fuzzing", gvk)
break
}
// if we expected defaulting, continue looping until the fuzzer gives us one
// at worst, we will timeout
}
iter++
src, err := scheme.New(gvk)
if err != nil {
t.Fatal(err)
}
f.Fuzz(src)
src.GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{})
original := src.DeepCopyObject()
// get internal
withDefaults := src.DeepCopyObject()
scheme.Default(withDefaults.(runtime.Object))
if !reflect.DeepEqual(original, withDefaults) {
changedOnce = true
if !expectedChanged {
t.Errorf("{Group: \"%s\", Version: \"%s\", Kind: \"%s\"} did not expect defaults to be set - update expected or check defaulter registering: %s", gvk.Group, gvk.Version, gvk.Kind, diff.ObjectReflectDiff(original, withDefaults))
}
}
}
}
}
func BenchmarkPodDefaulting(b *testing.B) {
f := fuzz.New().NilChance(.5).NumElements(1, 1).RandSource(rand.NewSource(1))
items := make([]apiv1.Pod, 100)
for i := range items {
f.Fuzz(&items[i])
}
scheme := api.Scheme
b.ResetTimer()
for i := 0; i < b.N; i++ {
pod := &items[i%len(items)]
scheme.Default(pod)
}
b.StopTimer()
}

View file

@ -9,7 +9,6 @@ load(
go_test(
name = "go_default_test",
srcs = ["helpers_test.go"],
importpath = "k8s.io/kubernetes/pkg/api/helper",
library = ":go_default_library",
deps = [
"//pkg/api:go_default_library",
@ -21,7 +20,6 @@ go_test(
go_library(
name = "go_default_library",
srcs = ["helpers.go"],
importpath = "k8s.io/kubernetes/pkg/api/helper",
deps = [
"//pkg/api:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",

View file

@ -265,11 +265,6 @@ func IsIntegerResourceName(str string) bool {
return integerResources.Has(str) || IsExtendedResourceName(api.ResourceName(str))
}
// Extended and HugePages resources
func IsScalarResourceName(name api.ResourceName) bool {
return IsExtendedResourceName(name) || IsHugePageResourceName(name)
}
// this function aims to check if the service's ClusterIP is set or not
// the objective is not to perform validation here
func IsServiceIPSet(service *api.Service) bool {

View file

@ -9,7 +9,6 @@ load(
go_library(
name = "go_default_library",
srcs = ["install.go"],
importpath = "k8s.io/kubernetes/pkg/api/install",
deps = [
"//pkg/api:go_default_library",
"//pkg/api/v1:go_default_library",
@ -23,7 +22,6 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["install_test.go"],
importpath = "k8s.io/kubernetes/pkg/api/install",
library = ":go_default_library",
deps = [
"//pkg/api:go_default_library",

103
vendor/k8s.io/kubernetes/pkg/api/meta_test.go generated vendored Normal file
View file

@ -0,0 +1,103 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed 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.
*/
package api_test
import (
"reflect"
"testing"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/api"
)
var _ metav1.Object = &metav1.ObjectMeta{}
func TestAccessorImplementations(t *testing.T) {
for _, gv := range api.Registry.EnabledVersions() {
internalGV := schema.GroupVersion{Group: gv.Group, Version: runtime.APIVersionInternal}
for _, gv := range []schema.GroupVersion{gv, internalGV} {
for kind, knownType := range api.Scheme.KnownTypes(gv) {
value := reflect.New(knownType)
obj := value.Interface()
if _, ok := obj.(runtime.Object); !ok {
t.Errorf("%v (%v) does not implement runtime.Object", gv.WithKind(kind), knownType)
}
lm, isLM := obj.(meta.ListMetaAccessor)
om, isOM := obj.(metav1.ObjectMetaAccessor)
switch {
case isLM && isOM:
t.Errorf("%v (%v) implements ListMetaAccessor and ObjectMetaAccessor", gv.WithKind(kind), knownType)
continue
case isLM:
m := lm.GetListMeta()
if m == nil {
t.Errorf("%v (%v) returns nil ListMeta", gv.WithKind(kind), knownType)
continue
}
m.SetResourceVersion("102030")
if m.GetResourceVersion() != "102030" {
t.Errorf("%v (%v) did not preserve resource version", gv.WithKind(kind), knownType)
continue
}
m.SetSelfLink("102030")
if m.GetSelfLink() != "102030" {
t.Errorf("%v (%v) did not preserve self link", gv.WithKind(kind), knownType)
continue
}
case isOM:
m := om.GetObjectMeta()
if m == nil {
t.Errorf("%v (%v) returns nil ObjectMeta", gv.WithKind(kind), knownType)
continue
}
m.SetResourceVersion("102030")
if m.GetResourceVersion() != "102030" {
t.Errorf("%v (%v) did not preserve resource version", gv.WithKind(kind), knownType)
continue
}
m.SetSelfLink("102030")
if m.GetSelfLink() != "102030" {
t.Errorf("%v (%v) did not preserve self link", gv.WithKind(kind), knownType)
continue
}
labels := map[string]string{"a": "b"}
m.SetLabels(labels)
if !reflect.DeepEqual(m.GetLabels(), labels) {
t.Errorf("%v (%v) did not preserve labels", gv.WithKind(kind), knownType)
continue
}
default:
if _, ok := obj.(metav1.ListMetaAccessor); ok {
continue
}
if _, ok := value.Elem().Type().FieldByName("ObjectMeta"); ok {
t.Errorf("%v (%v) has ObjectMeta but does not implement ObjectMetaAccessor", gv.WithKind(kind), knownType)
continue
}
if _, ok := value.Elem().Type().FieldByName("ListMeta"); ok {
t.Errorf("%v (%v) has ListMeta but does not implement ListMetaAccessor", gv.WithKind(kind), knownType)
continue
}
t.Logf("%v (%v) does not implement ListMetaAccessor or ObjectMetaAccessor", gv.WithKind(kind), knownType)
}
}
}
}
}

49
vendor/k8s.io/kubernetes/pkg/api/node_example.json generated vendored Normal file
View file

@ -0,0 +1,49 @@
{
"kind": "Node",
"apiVersion": "v1",
"metadata": {
"name": "e2e-test-wojtekt-node-etd6",
"selfLink": "/api/v1/nodes/e2e-test-wojtekt-node-etd6",
"uid": "a7e89222-e8e5-11e4-8fde-42010af09327",
"resourceVersion": "379",
"creationTimestamp": "2015-04-22T11:49:39Z"
},
"spec": {
"externalID": "15488322946290398375"
},
"status": {
"capacity": {
"cpu": "1",
"memory": "1745152Ki"
},
"conditions": [
{
"type": "Ready",
"status": "True",
"lastHeartbeatTime": "2015-04-22T11:58:17Z",
"lastTransitionTime": "2015-04-22T11:49:52Z",
"reason": "kubelet is posting ready status"
}
],
"addresses": [
{
"type": "ExternalIP",
"address": "104.197.49.213"
},
{
"type": "LegacyHostIP",
"address": "104.197.20.11"
}
],
"nodeInfo": {
"machineID": "",
"systemUUID": "D59FA3FA-7B5B-7287-5E1A-1D79F13CB577",
"bootID": "44a832f3-8cfb-4de5-b7d2-d66030b6cd95",
"kernelVersion": "3.16.0-0.bpo.4-amd64",
"osImage": "Debian GNU/Linux 7 (wheezy)",
"containerRuntimeVersion": "docker://1.5.0",
"kubeletVersion": "v0.15.0-484-g0c8ee980d705a3-dirty",
"kubeProxyVersion": "v0.15.0-484-g0c8ee980d705a3-dirty"
}
}
}

View file

@ -0,0 +1,83 @@
{
"kind": "ReplicationController",
"apiVersion": "v1",
"metadata": {
"name": "elasticsearch-logging-controller",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/replicationcontrollers/elasticsearch-logging-controller",
"uid": "aa76f162-e8e5-11e4-8fde-42010af09327",
"resourceVersion": "98",
"creationTimestamp": "2015-04-22T11:49:43Z",
"labels": {
"kubernetes.io/cluster-service": "true",
"name": "elasticsearch-logging"
}
},
"spec": {
"replicas": 1,
"selector": {
"name": "elasticsearch-logging"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"kubernetes.io/cluster-service": "true",
"name": "elasticsearch-logging"
}
},
"spec": {
"volumes": [
{
"name": "es-persistent-storage",
"hostPath": null,
"emptyDir": {
"medium": ""
},
"gcePersistentDisk": null,
"awsElasticBlockStore": null,
"gitRepo": null,
"secret": null,
"nfs": null,
"iscsi": null,
"glusterfs": null,
"quobyte": null
}
],
"containers": [
{
"name": "elasticsearch-logging",
"image": "gcr.io/google_containers/elasticsearch:1.0",
"ports": [
{
"name": "db",
"containerPort": 9200,
"protocol": "TCP"
},
{
"name": "transport",
"containerPort": 9300,
"protocol": "TCP"
}
],
"resources": {},
"volumeMounts": [
{
"name": "es-persistent-storage",
"mountPath": "/data"
}
],
"terminationMessagePath": "/dev/termination-log",
"imagePullPolicy": "IfNotPresent",
"capabilities": {}
}
],
"restartPolicy": "Always",
"dnsPolicy": "ClusterFirst"
}
}
},
"status": {
"replicas": 1
}
}

View file

@ -0,0 +1,217 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed 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.
*/
package api_test
import (
"bytes"
"encoding/hex"
"fmt"
"math/rand"
"reflect"
"testing"
"github.com/gogo/protobuf/proto"
"k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer/protobuf"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/kubernetes/pkg/api"
kapitesting "k8s.io/kubernetes/pkg/api/testing"
_ "k8s.io/kubernetes/pkg/apis/extensions"
_ "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
)
func TestUniversalDeserializer(t *testing.T) {
expected := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "test"}}
d := api.Codecs.UniversalDeserializer()
for _, mediaType := range []string{"application/json", "application/yaml", "application/vnd.kubernetes.protobuf"} {
info, ok := runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), mediaType)
if !ok {
t.Fatal(mediaType)
}
buf := &bytes.Buffer{}
if err := info.Serializer.Encode(expected, buf); err != nil {
t.Fatalf("%s: %v", mediaType, err)
}
obj, _, err := d.Decode(buf.Bytes(), &schema.GroupVersionKind{Kind: "Pod", Version: "v1"}, nil)
if err != nil {
t.Fatalf("%s: %v", mediaType, err)
}
if !apiequality.Semantic.DeepEqual(expected, obj) {
t.Fatalf("%s: %#v", mediaType, obj)
}
}
}
func TestAllFieldsHaveTags(t *testing.T) {
for gvk, obj := range api.Scheme.AllKnownTypes() {
if gvk.Version == runtime.APIVersionInternal {
// internal versions are not serialized to protobuf
continue
}
if gvk.Group == "componentconfig" {
// component config is not serialized to protobuf
continue
}
if err := fieldsHaveProtobufTags(obj); err != nil {
t.Errorf("type %s as gvk %v is missing tags: %v", obj, gvk, err)
}
}
}
func fieldsHaveProtobufTags(obj reflect.Type) error {
switch obj.Kind() {
case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Array:
return fieldsHaveProtobufTags(obj.Elem())
case reflect.Struct:
for i := 0; i < obj.NumField(); i++ {
f := obj.Field(i)
if f.Name == "TypeMeta" && f.Type.Name() == "TypeMeta" {
// TypeMeta is not included in external protobuf because we use an envelope type with TypeMeta
continue
}
if len(f.Tag.Get("json")) > 0 && len(f.Tag.Get("protobuf")) == 0 {
return fmt.Errorf("field %s in %s has a 'json' tag but no protobuf tag", f.Name, obj)
}
}
}
return nil
}
func TestProtobufRoundTrip(t *testing.T) {
obj := &v1.Pod{}
fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(benchmarkSeed), api.Codecs).Fuzz(obj)
// InitContainers are turned into annotations by conversion.
obj.Spec.InitContainers = nil
obj.Status.InitContainerStatuses = nil
data, err := obj.Marshal()
if err != nil {
t.Fatal(err)
}
out := &v1.Pod{}
if err := out.Unmarshal(data); err != nil {
t.Fatal(err)
}
if !apiequality.Semantic.Equalities.DeepEqual(out, obj) {
t.Logf("marshal\n%s", hex.Dump(data))
t.Fatalf("Unmarshal is unequal\n%s", diff.ObjectGoPrintDiff(out, obj))
}
}
// BenchmarkEncodeCodec measures the cost of performing a codec encode, which includes
// reflection (to clear APIVersion and Kind)
func BenchmarkEncodeCodecProtobuf(b *testing.B) {
items := benchmarkItems(b)
width := len(items)
s := protobuf.NewSerializer(nil, nil, "application/arbitrary.content.type")
b.ResetTimer()
for i := 0; i < b.N; i++ {
if _, err := runtime.Encode(s, &items[i%width]); err != nil {
b.Fatal(err)
}
}
b.StopTimer()
}
// BenchmarkEncodeCodecFromInternalProtobuf measures the cost of performing a codec encode,
// including conversions and any type setting. This is a "full" encode.
func BenchmarkEncodeCodecFromInternalProtobuf(b *testing.B) {
items := benchmarkItems(b)
width := len(items)
encodable := make([]api.Pod, width)
for i := range items {
if err := api.Scheme.Convert(&items[i], &encodable[i], nil); err != nil {
b.Fatal(err)
}
}
s := protobuf.NewSerializer(nil, nil, "application/arbitrary.content.type")
codec := api.Codecs.EncoderForVersion(s, v1.SchemeGroupVersion)
b.ResetTimer()
for i := 0; i < b.N; i++ {
if _, err := runtime.Encode(codec, &encodable[i%width]); err != nil {
b.Fatal(err)
}
}
b.StopTimer()
}
func BenchmarkEncodeProtobufGeneratedMarshal(b *testing.B) {
items := benchmarkItems(b)
width := len(items)
b.ResetTimer()
for i := 0; i < b.N; i++ {
if _, err := items[i%width].Marshal(); err != nil {
b.Fatal(err)
}
}
b.StopTimer()
}
// BenchmarkDecodeCodecToInternalProtobuf measures the cost of performing a codec decode,
// including conversions and any type setting. This is a "full" decode.
func BenchmarkDecodeCodecToInternalProtobuf(b *testing.B) {
items := benchmarkItems(b)
width := len(items)
s := protobuf.NewSerializer(api.Scheme, api.Scheme, "application/arbitrary.content.type")
encoder := api.Codecs.EncoderForVersion(s, v1.SchemeGroupVersion)
var encoded [][]byte
for i := range items {
data, err := runtime.Encode(encoder, &items[i])
if err != nil {
b.Fatal(err)
}
encoded = append(encoded, data)
}
decoder := api.Codecs.DecoderToVersion(s, api.SchemeGroupVersion)
b.ResetTimer()
for i := 0; i < b.N; i++ {
if _, err := runtime.Decode(decoder, encoded[i%width]); err != nil {
b.Fatal(err)
}
}
b.StopTimer()
}
// BenchmarkDecodeJSON provides a baseline for regular JSON decode performance
func BenchmarkDecodeIntoProtobuf(b *testing.B) {
items := benchmarkItems(b)
width := len(items)
encoded := make([][]byte, width)
for i := range items {
data, err := (&items[i]).Marshal()
if err != nil {
b.Fatal(err)
}
encoded[i] = data
validate := &v1.Pod{}
if err := proto.Unmarshal(data, validate); err != nil {
b.Fatalf("Failed to unmarshal %d: %v\n%#v", i, err, items[i])
}
}
for i := 0; i < b.N; i++ {
obj := v1.Pod{}
if err := proto.Unmarshal(encoded[i%width], &obj); err != nil {
b.Fatal(err)
}
}
}

561
vendor/k8s.io/kubernetes/pkg/api/serialization_test.go generated vendored Normal file
View file

@ -0,0 +1,561 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed 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.
*/
package api_test
import (
"bytes"
"encoding/hex"
"encoding/json"
"io/ioutil"
"math/rand"
"reflect"
"strings"
"testing"
"github.com/golang/protobuf/proto"
jsoniter "github.com/json-iterator/go"
"k8s.io/api/core/v1"
"k8s.io/api/extensions/v1beta1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
"k8s.io/apimachinery/pkg/api/testing/roundtrip"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer/streaming"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi"
kapitesting "k8s.io/kubernetes/pkg/api/testing"
k8s_api_v1 "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/apis/extensions"
k8s_v1beta1 "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
)
// fuzzInternalObject fuzzes an arbitrary runtime object using the appropriate
// fuzzer registered with the apitesting package.
func fuzzInternalObject(t *testing.T, forVersion schema.GroupVersion, item runtime.Object, seed int64) runtime.Object {
fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(seed), api.Codecs).Fuzz(item)
j, err := meta.TypeAccessor(item)
if err != nil {
t.Fatalf("Unexpected error %v for %#v", err, item)
}
j.SetKind("")
j.SetAPIVersion("")
return item
}
// dataAsString returns the given byte array as a string; handles detecting
// protocol buffers.
func dataAsString(data []byte) string {
dataString := string(data)
if !strings.HasPrefix(dataString, "{") {
dataString = "\n" + hex.Dump(data)
proto.NewBuffer(make([]byte, 0, 1024)).DebugPrint("decoded object", data)
}
return dataString
}
func Convert_v1beta1_ReplicaSet_to_api_ReplicationController(in *v1beta1.ReplicaSet, out *api.ReplicationController, s conversion.Scope) error {
intermediate1 := &extensions.ReplicaSet{}
if err := k8s_v1beta1.Convert_v1beta1_ReplicaSet_To_extensions_ReplicaSet(in, intermediate1, s); err != nil {
return err
}
intermediate2 := &v1.ReplicationController{}
if err := k8s_api_v1.Convert_extensions_ReplicaSet_to_v1_ReplicationController(intermediate1, intermediate2, s); err != nil {
return err
}
return k8s_api_v1.Convert_v1_ReplicationController_To_api_ReplicationController(intermediate2, out, s)
}
func TestSetControllerConversion(t *testing.T) {
if err := api.Scheme.AddConversionFuncs(Convert_v1beta1_ReplicaSet_to_api_ReplicationController); err != nil {
t.Fatal(err)
}
rs := &extensions.ReplicaSet{}
rc := &api.ReplicationController{}
extGroup := testapi.Extensions
defaultGroup := testapi.Default
fuzzInternalObject(t, extGroup.InternalGroupVersion(), rs, rand.Int63())
t.Logf("rs._internal.extensions -> rs.v1beta1.extensions")
data, err := runtime.Encode(extGroup.Codec(), rs)
if err != nil {
t.Fatalf("unexpected encoding error: %v", err)
}
decoder := api.Codecs.DecoderToVersion(
api.Codecs.UniversalDeserializer(),
runtime.NewMultiGroupVersioner(
*defaultGroup.GroupVersion(),
schema.GroupKind{Group: defaultGroup.GroupVersion().Group},
schema.GroupKind{Group: extGroup.GroupVersion().Group},
),
)
t.Logf("rs.v1beta1.extensions -> rc._internal")
if err := runtime.DecodeInto(decoder, data, rc); err != nil {
t.Fatalf("unexpected decoding error: %v", err)
}
t.Logf("rc._internal -> rc.v1")
data, err = runtime.Encode(defaultGroup.Codec(), rc)
if err != nil {
t.Fatalf("unexpected encoding error: %v", err)
}
t.Logf("rc.v1 -> rs._internal.extensions")
if err := runtime.DecodeInto(decoder, data, rs); err != nil {
t.Fatalf("unexpected decoding error: %v", err)
}
}
// TestSpecificKind round-trips a single specific kind and is intended to help
// debug issues that arise while adding a new API type.
func TestSpecificKind(t *testing.T) {
// Uncomment the following line to enable logging of which conversions
// api.Scheme.Log(t)
internalGVK := schema.GroupVersionKind{Group: "extensions", Version: runtime.APIVersionInternal, Kind: "DaemonSet"}
seed := rand.Int63()
fuzzer := fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(seed), api.Codecs)
roundtrip.RoundTripSpecificKind(t, internalGVK, api.Scheme, api.Codecs, fuzzer, nil)
}
var nonRoundTrippableTypes = sets.NewString(
"ExportOptions",
"GetOptions",
// WatchEvent does not include kind and version and can only be deserialized
// implicitly (if the caller expects the specific object). The watch call defines
// the schema by content type, rather than via kind/version included in each
// object.
"WatchEvent",
// ListOptions is now part of the meta group
"ListOptions",
// Delete options is only read in metav1
"DeleteOptions",
)
var commonKinds = []string{"Status", "ListOptions", "DeleteOptions", "ExportOptions"}
// TestCommonKindsRegistered verifies that all group/versions registered with
// the testapi package have the common kinds.
func TestCommonKindsRegistered(t *testing.T) {
for _, kind := range commonKinds {
for _, group := range testapi.Groups {
gv := group.GroupVersion()
gvk := gv.WithKind(kind)
obj, err := api.Scheme.New(gvk)
if err != nil {
t.Error(err)
}
defaults := gv.WithKind("")
var got *schema.GroupVersionKind
if obj, got, err = api.Codecs.LegacyCodec().Decode([]byte(`{"kind":"`+kind+`"}`), &defaults, obj); err != nil || gvk != *got {
t.Errorf("expected %v: %v %v", gvk, got, err)
}
data, err := runtime.Encode(api.Codecs.LegacyCodec(*gv), obj)
if err != nil {
t.Errorf("expected %v: %v\n%s", gvk, err, string(data))
continue
}
if !bytes.Contains(data, []byte(`"kind":"`+kind+`","apiVersion":"`+gv.String()+`"`)) {
if kind != "Status" {
t.Errorf("expected %v: %v\n%s", gvk, err, string(data))
continue
}
// TODO: this is wrong, but legacy clients expect it
if !bytes.Contains(data, []byte(`"kind":"`+kind+`","apiVersion":"v1"`)) {
t.Errorf("expected %v: %v\n%s", gvk, err, string(data))
continue
}
}
}
}
}
// TestRoundTripTypes applies the round-trip test to all round-trippable Kinds
// in all of the API groups registered for test in the testapi package.
func TestRoundTripTypes(t *testing.T) {
seed := rand.Int63()
fuzzer := fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(seed), api.Codecs)
nonRoundTrippableTypes := map[schema.GroupVersionKind]bool{
{Group: "componentconfig", Version: runtime.APIVersionInternal, Kind: "KubeProxyConfiguration"}: true,
{Group: "componentconfig", Version: runtime.APIVersionInternal, Kind: "KubeSchedulerConfiguration"}: true,
}
roundtrip.RoundTripTypes(t, api.Scheme, api.Codecs, fuzzer, nonRoundTrippableTypes)
}
// TestEncodePtr tests that a pointer to a golang type can be encoded and
// decoded without information loss or mutation.
func TestEncodePtr(t *testing.T) {
grace := int64(30)
pod := &api.Pod{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"name": "foo"},
},
Spec: api.PodSpec{
RestartPolicy: api.RestartPolicyAlways,
DNSPolicy: api.DNSClusterFirst,
TerminationGracePeriodSeconds: &grace,
SecurityContext: &api.PodSecurityContext{},
SchedulerName: api.DefaultSchedulerName,
},
}
obj := runtime.Object(pod)
data, err := runtime.Encode(testapi.Default.Codec(), obj)
obj2, err2 := runtime.Decode(testapi.Default.Codec(), data)
if err != nil || err2 != nil {
t.Fatalf("Failure: '%v' '%v'", err, err2)
}
if _, ok := obj2.(*api.Pod); !ok {
t.Fatalf("Got wrong type")
}
if !apiequality.Semantic.DeepEqual(obj2, pod) {
t.Errorf("\nExpected:\n\n %#v,\n\nGot:\n\n %#vDiff: %v\n\n", pod, obj2, diff.ObjectDiff(obj2, pod))
}
}
// TestBadJSONRejection establishes that a JSON object without a kind or with
// an unknown kind will not be decoded without error.
func TestBadJSONRejection(t *testing.T) {
badJSONMissingKind := []byte(`{ }`)
if _, err := runtime.Decode(testapi.Default.Codec(), badJSONMissingKind); err == nil {
t.Errorf("Did not reject despite lack of kind field: %s", badJSONMissingKind)
}
badJSONUnknownType := []byte(`{"kind": "bar"}`)
if _, err1 := runtime.Decode(testapi.Default.Codec(), badJSONUnknownType); err1 == nil {
t.Errorf("Did not reject despite use of unknown type: %s", badJSONUnknownType)
}
/*badJSONKindMismatch := []byte(`{"kind": "Pod"}`)
if err2 := DecodeInto(badJSONKindMismatch, &Node{}); err2 == nil {
t.Errorf("Kind is set but doesn't match the object type: %s", badJSONKindMismatch)
}*/
}
// TestUnversionedTypes establishes that the default codec can encode and
// decode unversioned objects.
func TestUnversionedTypes(t *testing.T) {
testcases := []runtime.Object{
&metav1.Status{Status: "Failure", Message: "something went wrong"},
&metav1.APIVersions{Versions: []string{"A", "B", "C"}},
&metav1.APIGroupList{Groups: []metav1.APIGroup{{Name: "mygroup"}}},
&metav1.APIGroup{Name: "mygroup"},
&metav1.APIResourceList{GroupVersion: "mygroup/myversion"},
}
for _, obj := range testcases {
// Make sure the unversioned codec can encode
unversionedJSON, err := runtime.Encode(testapi.Default.Codec(), obj)
if err != nil {
t.Errorf("%v: unexpected error: %v", obj, err)
continue
}
// Make sure the versioned codec under test can decode
versionDecodedObject, err := runtime.Decode(testapi.Default.Codec(), unversionedJSON)
if err != nil {
t.Errorf("%v: unexpected error: %v", obj, err)
continue
}
// Make sure it decodes correctly
if !reflect.DeepEqual(obj, versionDecodedObject) {
t.Errorf("%v: expected %#v, got %#v", obj, obj, versionDecodedObject)
continue
}
}
}
// TestObjectWatchFraming establishes that a watch event can be encoded and
// decoded correctly through each of the supported RFC2046 media types.
func TestObjectWatchFraming(t *testing.T) {
f := fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(benchmarkSeed), api.Codecs)
secret := &api.Secret{}
f.Fuzz(secret)
secret.Data["binary"] = []byte{0x00, 0x10, 0x30, 0x55, 0xff, 0x00}
secret.Data["utf8"] = []byte("a string with \u0345 characters")
secret.Data["long"] = bytes.Repeat([]byte{0x01, 0x02, 0x03, 0x00}, 1000)
converted, _ := api.Scheme.ConvertToVersion(secret, v1.SchemeGroupVersion)
v1secret := converted.(*v1.Secret)
for _, info := range api.Codecs.SupportedMediaTypes() {
if info.StreamSerializer == nil {
continue
}
s := info.StreamSerializer
framer := s.Framer
embedded := info.Serializer
if embedded == nil {
t.Errorf("no embedded serializer for %s", info.MediaType)
continue
}
innerDecode := api.Codecs.DecoderToVersion(embedded, api.SchemeGroupVersion)
// write a single object through the framer and back out
obj := &bytes.Buffer{}
if err := s.Encode(v1secret, obj); err != nil {
t.Fatal(err)
}
out := &bytes.Buffer{}
w := framer.NewFrameWriter(out)
if n, err := w.Write(obj.Bytes()); err != nil || n != len(obj.Bytes()) {
t.Fatal(err)
}
sr := streaming.NewDecoder(framer.NewFrameReader(ioutil.NopCloser(out)), s)
resultSecret := &v1.Secret{}
res, _, err := sr.Decode(nil, resultSecret)
if err != nil {
t.Fatalf("%v:\n%s", err, hex.Dump(obj.Bytes()))
}
resultSecret.Kind = "Secret"
resultSecret.APIVersion = "v1"
if !apiequality.Semantic.DeepEqual(v1secret, res) {
t.Fatalf("objects did not match: %s", diff.ObjectGoPrintDiff(v1secret, res))
}
// write a watch event through the frame writer and read it back in
// via the frame reader for this media type
obj = &bytes.Buffer{}
if err := embedded.Encode(v1secret, obj); err != nil {
t.Fatal(err)
}
event := &metav1.WatchEvent{Type: string(watch.Added)}
event.Object.Raw = obj.Bytes()
obj = &bytes.Buffer{}
if err := s.Encode(event, obj); err != nil {
t.Fatal(err)
}
out = &bytes.Buffer{}
w = framer.NewFrameWriter(out)
if n, err := w.Write(obj.Bytes()); err != nil || n != len(obj.Bytes()) {
t.Fatal(err)
}
sr = streaming.NewDecoder(framer.NewFrameReader(ioutil.NopCloser(out)), s)
outEvent := &metav1.WatchEvent{}
res, _, err = sr.Decode(nil, outEvent)
if err != nil || outEvent.Type != string(watch.Added) {
t.Fatalf("%v: %#v", err, outEvent)
}
if outEvent.Object.Object == nil && outEvent.Object.Raw != nil {
outEvent.Object.Object, err = runtime.Decode(innerDecode, outEvent.Object.Raw)
if err != nil {
t.Fatalf("%v:\n%s", err, hex.Dump(outEvent.Object.Raw))
}
}
if !apiequality.Semantic.DeepEqual(secret, outEvent.Object.Object) {
t.Fatalf("%s: did not match after frame decoding: %s", info.MediaType, diff.ObjectGoPrintDiff(secret, outEvent.Object.Object))
}
}
}
const benchmarkSeed = 100
func benchmarkItems(b *testing.B) []v1.Pod {
apiObjectFuzzer := fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(benchmarkSeed), api.Codecs)
items := make([]v1.Pod, 10)
for i := range items {
var pod api.Pod
apiObjectFuzzer.Fuzz(&pod)
pod.Spec.InitContainers, pod.Status.InitContainerStatuses = nil, nil
out, err := api.Scheme.ConvertToVersion(&pod, v1.SchemeGroupVersion)
if err != nil {
panic(err)
}
items[i] = *out.(*v1.Pod)
}
return items
}
// BenchmarkEncodeCodec measures the cost of performing a codec encode, which includes
// reflection (to clear APIVersion and Kind)
func BenchmarkEncodeCodec(b *testing.B) {
items := benchmarkItems(b)
width := len(items)
b.ResetTimer()
for i := 0; i < b.N; i++ {
if _, err := runtime.Encode(testapi.Default.Codec(), &items[i%width]); err != nil {
b.Fatal(err)
}
}
b.StopTimer()
}
// BenchmarkEncodeCodecFromInternal measures the cost of performing a codec encode,
// including conversions.
func BenchmarkEncodeCodecFromInternal(b *testing.B) {
items := benchmarkItems(b)
width := len(items)
encodable := make([]api.Pod, width)
for i := range items {
if err := api.Scheme.Convert(&items[i], &encodable[i], nil); err != nil {
b.Fatal(err)
}
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
if _, err := runtime.Encode(testapi.Default.Codec(), &encodable[i%width]); err != nil {
b.Fatal(err)
}
}
b.StopTimer()
}
// BenchmarkEncodeJSONMarshal provides a baseline for regular JSON encode performance
func BenchmarkEncodeJSONMarshal(b *testing.B) {
items := benchmarkItems(b)
width := len(items)
b.ResetTimer()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(&items[i%width]); err != nil {
b.Fatal(err)
}
}
b.StopTimer()
}
func BenchmarkDecodeCodec(b *testing.B) {
codec := testapi.Default.Codec()
items := benchmarkItems(b)
width := len(items)
encoded := make([][]byte, width)
for i := range items {
data, err := runtime.Encode(codec, &items[i])
if err != nil {
b.Fatal(err)
}
encoded[i] = data
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
if _, err := runtime.Decode(codec, encoded[i%width]); err != nil {
b.Fatal(err)
}
}
b.StopTimer()
}
func BenchmarkDecodeIntoExternalCodec(b *testing.B) {
codec := testapi.Default.Codec()
items := benchmarkItems(b)
width := len(items)
encoded := make([][]byte, width)
for i := range items {
data, err := runtime.Encode(codec, &items[i])
if err != nil {
b.Fatal(err)
}
encoded[i] = data
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
obj := v1.Pod{}
if err := runtime.DecodeInto(codec, encoded[i%width], &obj); err != nil {
b.Fatal(err)
}
}
b.StopTimer()
}
func BenchmarkDecodeIntoInternalCodec(b *testing.B) {
codec := testapi.Default.Codec()
items := benchmarkItems(b)
width := len(items)
encoded := make([][]byte, width)
for i := range items {
data, err := runtime.Encode(codec, &items[i])
if err != nil {
b.Fatal(err)
}
encoded[i] = data
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
obj := api.Pod{}
if err := runtime.DecodeInto(codec, encoded[i%width], &obj); err != nil {
b.Fatal(err)
}
}
b.StopTimer()
}
// BenchmarkDecodeJSON provides a baseline for regular JSON decode performance
func BenchmarkDecodeIntoJSON(b *testing.B) {
codec := testapi.Default.Codec()
items := benchmarkItems(b)
width := len(items)
encoded := make([][]byte, width)
for i := range items {
data, err := runtime.Encode(codec, &items[i])
if err != nil {
b.Fatal(err)
}
encoded[i] = data
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
obj := v1.Pod{}
if err := json.Unmarshal(encoded[i%width], &obj); err != nil {
b.Fatal(err)
}
}
b.StopTimer()
}
// BenchmarkDecodeJSON provides a baseline for JSON decode performance
func BenchmarkDecodeIntoJSONCodecGen(b *testing.B) {
kcodec := testapi.Default.Codec()
items := benchmarkItems(b)
width := len(items)
encoded := make([][]byte, width)
for i := range items {
data, err := runtime.Encode(kcodec, &items[i])
if err != nil {
b.Fatal(err)
}
encoded[i] = data
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
obj := v1.Pod{}
if err := jsoniter.ConfigFastest.Unmarshal(encoded[i%width], &obj); err != nil {
b.Fatal(err)
}
}
b.StopTimer()
}

View file

@ -9,7 +9,6 @@ load(
go_library(
name = "go_default_library",
srcs = ["util.go"],
importpath = "k8s.io/kubernetes/pkg/api/service",
deps = [
"//pkg/api:go_default_library",
"//pkg/util/net/sets:go_default_library",
@ -19,7 +18,6 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["util_test.go"],
importpath = "k8s.io/kubernetes/pkg/api/service",
library = ":go_default_library",
deps = [
"//pkg/api:go_default_library",

View file

@ -1238,7 +1238,7 @@ type AzureDiskVolumeSource struct {
// the ReadOnly setting in VolumeMounts.
// +optional
ReadOnly *bool
// Expected values Shared: multiple blob disks per storage account Dedicated: single blob disk per storage account Managed: azure managed data disk (only in managed availability set). defaults to shared
// Expected values Shared: mulitple blob disks per storage account Dedicated: single blob disk per storage account Managed: azure managed data disk (only in managed availability set). defaults to shared
Kind *AzureDataDiskKind
}
@ -2229,7 +2229,7 @@ type Taint struct {
// TimeAdded represents the time at which the taint was added.
// It is only written for NoExecute taints.
// +optional
TimeAdded *metav1.Time
TimeAdded metav1.Time
}
type TaintEffect string
@ -3117,7 +3117,7 @@ type NodeConfigSource struct {
type DaemonEndpoint struct {
/*
The port tag was not properly in quotes in earlier releases, so it must be
uppercase for backwards compatibility (since it was falling back to var name of
uppercased for backwards compat (since it was falling back to var name of
'Port').
*/
@ -4043,7 +4043,7 @@ const (
// BasicAuthPasswordKey is the key of the password or token for SecretTypeBasicAuth secrets
BasicAuthPasswordKey = "password"
// SecretTypeSSHAuth contains data needed for SSH authentication.
// SecretTypeSSHAuth contains data needed for SSH authetication.
//
// Required field:
// - Secret.Data["ssh-privatekey"] - private SSH key needed for authentication

174
vendor/k8s.io/kubernetes/pkg/api/unstructured_test.go generated vendored Normal file
View file

@ -0,0 +1,174 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed 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.
*/
package api_test
import (
"math/rand"
"reflect"
"testing"
"github.com/google/gofuzz"
"k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
"k8s.io/apimachinery/pkg/conversion/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apimachinery/pkg/util/json"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi"
kapitesting "k8s.io/kubernetes/pkg/api/testing"
)
func doRoundTrip(t *testing.T, group testapi.TestGroup, kind string) {
// We do fuzzing on the internal version of the object, and only then
// convert to the external version. This is because custom fuzzing
// function are only supported for internal objects.
internalObj, err := api.Scheme.New(group.InternalGroupVersion().WithKind(kind))
if err != nil {
t.Fatalf("Couldn't create internal object %v: %v", kind, err)
}
seed := rand.Int63()
fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(seed), api.Codecs).
// We are explicitly overwriting custom fuzzing functions, to ensure
// that InitContainers and their statuses are not generated. This is
// because in thise test we are simply doing json operations, in which
// those disappear.
Funcs(
func(s *api.PodSpec, c fuzz.Continue) {
c.FuzzNoCustom(s)
s.InitContainers = nil
},
func(s *api.PodStatus, c fuzz.Continue) {
c.FuzzNoCustom(s)
s.InitContainerStatuses = nil
},
).Fuzz(internalObj)
item, err := api.Scheme.New(group.GroupVersion().WithKind(kind))
if err != nil {
t.Fatalf("Couldn't create external object %v: %v", kind, err)
}
if err := api.Scheme.Convert(internalObj, item, nil); err != nil {
t.Fatalf("Conversion for %v failed: %v", kind, err)
}
data, err := json.Marshal(item)
if err != nil {
t.Errorf("Error when marshaling object: %v", err)
return
}
unstr := make(map[string]interface{})
err = json.Unmarshal(data, &unstr)
if err != nil {
t.Errorf("Error when unmarshaling to unstructured: %v", err)
return
}
data, err = json.Marshal(unstr)
if err != nil {
t.Errorf("Error when marshaling unstructured: %v", err)
return
}
unmarshalledObj := reflect.New(reflect.TypeOf(item).Elem()).Interface()
err = json.Unmarshal(data, &unmarshalledObj)
if err != nil {
t.Errorf("Error when unmarshaling to object: %v", err)
return
}
if !apiequality.Semantic.DeepEqual(item, unmarshalledObj) {
t.Errorf("Object changed during JSON operations, diff: %v", diff.ObjectReflectDiff(item, unmarshalledObj))
return
}
newUnstr, err := unstructured.DefaultConverter.ToUnstructured(item)
if err != nil {
t.Errorf("ToUnstructured failed: %v", err)
return
}
newObj := reflect.New(reflect.TypeOf(item).Elem()).Interface().(runtime.Object)
err = unstructured.DefaultConverter.FromUnstructured(newUnstr, newObj)
if err != nil {
t.Errorf("FromUnstructured failed: %v", err)
return
}
if !apiequality.Semantic.DeepEqual(item, newObj) {
t.Errorf("Object changed, diff: %v", diff.ObjectReflectDiff(item, newObj))
}
}
func TestRoundTrip(t *testing.T) {
for groupKey, group := range testapi.Groups {
for kind := range group.ExternalTypes() {
if nonRoundTrippableTypes.Has(kind) {
continue
}
t.Logf("Testing: %v in %v", kind, groupKey)
for i := 0; i < 50; i++ {
doRoundTrip(t, group, kind)
if t.Failed() {
break
}
}
}
}
}
func BenchmarkToFromUnstructured(b *testing.B) {
items := benchmarkItems(b)
size := len(items)
b.ResetTimer()
for i := 0; i < b.N; i++ {
unstr, err := unstructured.DefaultConverter.ToUnstructured(&items[i%size])
if err != nil {
b.Fatalf("unexpected error: %v", err)
}
obj := v1.Pod{}
if err := unstructured.DefaultConverter.FromUnstructured(unstr, &obj); err != nil {
b.Fatalf("unexpected error: %v", err)
}
}
b.StopTimer()
}
func BenchmarkToFromUnstructuredViaJSON(b *testing.B) {
items := benchmarkItems(b)
size := len(items)
b.ResetTimer()
for i := 0; i < b.N; i++ {
data, err := json.Marshal(&items[i%size])
if err != nil {
b.Fatalf("unexpected error: %v", err)
}
unstr := map[string]interface{}{}
if err := json.Unmarshal(data, &unstr); err != nil {
b.Fatalf("unexpected error: %v", err)
}
data, err = json.Marshal(unstr)
if err != nil {
b.Fatalf("unexpected error: %v", err)
}
obj := v1.Pod{}
if err := json.Unmarshal(data, &obj); err != nil {
b.Fatalf("unexpected error: %v", err)
}
}
b.StopTimer()
}

31
vendor/k8s.io/kubernetes/pkg/api/util/BUILD generated vendored Normal file
View file

@ -0,0 +1,31 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = ["group_version.go"],
)
go_test(
name = "go_default_test",
srcs = ["group_version_test.go"],
library = ":go_default_library",
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

3
vendor/k8s.io/kubernetes/pkg/api/util/OWNERS generated vendored Executable file
View file

@ -0,0 +1,3 @@
reviewers:
- caesarxuchao
- david-mcmahon

48
vendor/k8s.io/kubernetes/pkg/api/util/group_version.go generated vendored Normal file
View file

@ -0,0 +1,48 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed 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.
*/
// TODO: This GetVersion/GetGroup arrangement is temporary and will be replaced
// with a GroupAndVersion type.
package util
import "strings"
func GetVersion(groupVersion string) string {
s := strings.Split(groupVersion, "/")
if len(s) != 2 {
// e.g. return "v1" for groupVersion="v1"
return s[len(s)-1]
}
return s[1]
}
func GetGroup(groupVersion string) string {
s := strings.Split(groupVersion, "/")
if len(s) == 1 {
// e.g. return "" for groupVersion="v1"
return ""
}
return s[0]
}
// GetGroupVersion returns the "group/version". It returns "version" is if group
// is empty. It returns "group/" if version is empty.
func GetGroupVersion(group, version string) string {
if len(group) == 0 {
return version
}
return group + "/" + version
}

View file

@ -0,0 +1,93 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed 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.
*/
package util
import "testing"
func TestGetVersion(t *testing.T) {
testCases := []struct {
groupVersion string
output string
}{
{
"v1",
"v1",
},
{
"extensions/v1beta1",
"v1beta1",
},
}
for _, test := range testCases {
actual := GetVersion(test.groupVersion)
if test.output != actual {
t.Errorf("expect version: %s, got: %s\n", test.output, actual)
}
}
}
func TestGetGroup(t *testing.T) {
testCases := []struct {
groupVersion string
output string
}{
{
"v1",
"",
},
{
"extensions/v1beta1",
"extensions",
},
}
for _, test := range testCases {
actual := GetGroup(test.groupVersion)
if test.output != actual {
t.Errorf("expect version: %s, got: %s\n", test.output, actual)
}
}
}
func TestGetGroupVersion(t *testing.T) {
testCases := []struct {
group string
version string
output string
}{
{
"",
"v1",
"v1",
},
{
"extensions",
"",
"extensions/",
},
{
"extensions",
"v1beta1",
"extensions/v1beta1",
},
}
for _, test := range testCases {
actual := GetGroupVersion(test.group, test.version)
if test.output != actual {
t.Errorf("expect version: %s, got: %s\n", test.output, actual)
}
}
}

View file

@ -12,11 +12,11 @@ go_library(
"conversion.go",
"defaults.go",
"doc.go",
"generate.go",
"register.go",
"zz_generated.conversion.go",
"zz_generated.defaults.go",
],
importpath = "k8s.io/kubernetes/pkg/api/v1",
deps = [
"//pkg/api:go_default_library",
"//pkg/apis/extensions:go_default_library",
@ -30,6 +30,7 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/rand:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
],
)
@ -37,14 +38,16 @@ go_library(
go_test(
name = "go_default_xtest",
srcs = [
"backward_compatibility_test.go",
"conversion_test.go",
"defaults_test.go",
],
importpath = "k8s.io/kubernetes/pkg/api/v1_test",
deps = [
":go_default_library",
"//pkg/api:go_default_library",
"//pkg/api/testapi:go_default_library",
"//pkg/api/install:go_default_library",
"//pkg/api/testing/compat:go_default_library",
"//pkg/api/validation:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
@ -52,6 +55,7 @@ go_test(
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
],
)

View file

@ -0,0 +1,169 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed 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.
*/
package v1_test
import (
"testing"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testing/compat"
"k8s.io/kubernetes/pkg/api/validation"
_ "k8s.io/kubernetes/pkg/api/install"
)
func TestCompatibility_v1_PodSecurityContext(t *testing.T) {
cases := []struct {
name string
input string
expectedKeys map[string]string
absentKeys []string
}{
{
name: "hostNetwork = true",
input: `
{
"kind":"Pod",
"apiVersion":"v1",
"metadata":{"name":"my-pod-name", "namespace":"my-pod-namespace"},
"spec": {
"hostNetwork": true,
"containers":[{
"name":"a",
"image":"my-container-image"
}]
}
}
`,
expectedKeys: map[string]string{
"spec.hostNetwork": "true",
},
},
{
name: "hostNetwork = false",
input: `
{
"kind":"Pod",
"apiVersion":"v1",
"metadata":{"name":"my-pod-name", "namespace":"my-pod-namespace"},
"spec": {
"hostNetwork": false,
"containers":[{
"name":"a",
"image":"my-container-image"
}]
}
}
`,
absentKeys: []string{
"spec.hostNetwork",
},
},
{
name: "hostIPC = true",
input: `
{
"kind":"Pod",
"apiVersion":"v1",
"metadata":{"name":"my-pod-name", "namespace":"my-pod-namespace"},
"spec": {
"hostIPC": true,
"containers":[{
"name":"a",
"image":"my-container-image"
}]
}
}
`,
expectedKeys: map[string]string{
"spec.hostIPC": "true",
},
},
{
name: "hostIPC = false",
input: `
{
"kind":"Pod",
"apiVersion":"v1",
"metadata":{"name":"my-pod-name", "namespace":"my-pod-namespace"},
"spec": {
"hostIPC": false,
"containers":[{
"name":"a",
"image":"my-container-image"
}]
}
}
`,
absentKeys: []string{
"spec.hostIPC",
},
},
{
name: "hostPID = true",
input: `
{
"kind":"Pod",
"apiVersion":"v1",
"metadata":{"name":"my-pod-name", "namespace":"my-pod-namespace"},
"spec": {
"hostPID": true,
"containers":[{
"name":"a",
"image":"my-container-image"
}]
}
}
`,
expectedKeys: map[string]string{
"spec.hostPID": "true",
},
},
{
name: "hostPID = false",
input: `
{
"kind":"Pod",
"apiVersion":"v1",
"metadata":{"name":"my-pod-name", "namespace":"my-pod-namespace"},
"spec": {
"hostPID": false,
"containers":[{
"name":"a",
"image":"my-container-image"
}]
}
}
`,
absentKeys: []string{
"spec.hostPID",
},
},
}
validator := func(obj runtime.Object) field.ErrorList {
return validation.ValidatePodSpec(&(obj.(*api.Pod).Spec), field.NewPath("spec"))
}
for _, tc := range cases {
t.Logf("Testing 1.0.0 backward compatibility for %v", tc.name)
compat.TestCompatibility(t, v1.SchemeGroupVersion, []byte(tc.input), validator, tc.expectedKeys, tc.absentKeys)
}
}

View file

@ -30,9 +30,6 @@ import (
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/kubernetes/pkg/api"
k8s_api_v1 "k8s.io/kubernetes/pkg/api/v1"
// enforce that all types are installed
_ "k8s.io/kubernetes/pkg/api/testapi"
)
func TestPodLogOptions(t *testing.T) {

View file

@ -28,9 +28,6 @@ import (
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/kubernetes/pkg/api"
k8s_api_v1 "k8s.io/kubernetes/pkg/api/v1"
// enforce that all types are installed
_ "k8s.io/kubernetes/pkg/api/testapi"
)
func roundTrip(t *testing.T, obj runtime.Object) runtime.Object {

65
vendor/k8s.io/kubernetes/pkg/api/v1/generate.go generated vendored Normal file
View file

@ -0,0 +1,65 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed 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.
*/
package v1
import (
"fmt"
"k8s.io/api/core/v1"
utilrand "k8s.io/apimachinery/pkg/util/rand"
)
// NameGenerator generates names for objects. Some backends may have more information
// available to guide selection of new names and this interface hides those details.
type NameGenerator interface {
// GenerateName generates a valid name from the base name, adding a random suffix to the
// the base. If base is valid, the returned name must also be valid. The generator is
// responsible for knowing the maximum valid name length.
GenerateName(base string) string
}
// GenerateName will resolve the object name of the provided v1.ObjectMeta to a generated version if
// necessary. It expects that validation for v1.ObjectMeta has already completed (that Base is a
// valid name) and that the NameGenerator generates a name that is also valid.
func GenerateName(u NameGenerator, meta *v1.ObjectMeta) {
if len(meta.GenerateName) == 0 || len(meta.Name) != 0 {
return
}
meta.Name = u.GenerateName(meta.GenerateName)
}
// simpleNameGenerator generates random names.
type simpleNameGenerator struct{}
// SimpleNameGenerator is a generator that returns the name plus a random suffix of five alphanumerics
// when a name is requested. The string is guaranteed to not exceed the length of a standard Kubernetes
// name (63 characters)
var SimpleNameGenerator NameGenerator = simpleNameGenerator{}
const (
// TODO: make this flexible for non-core resources with alternate naming rules.
maxNameLength = 63
randomLength = 5
maxGeneratedNameLength = maxNameLength - randomLength
)
func (simpleNameGenerator) GenerateName(base string) string {
if len(base) > maxGeneratedNameLength {
base = base[:maxGeneratedNameLength]
}
return fmt.Sprintf("%s%s", base, utilrand.String(randomLength))
}

View file

@ -9,7 +9,6 @@ load(
go_test(
name = "go_default_test",
srcs = ["helpers_test.go"],
importpath = "k8s.io/kubernetes/pkg/api/v1/helper",
library = ":go_default_library",
deps = [
"//vendor/k8s.io/api/core/v1:go_default_library",
@ -22,7 +21,6 @@ go_test(
go_library(
name = "go_default_library",
srcs = ["helpers.go"],
importpath = "k8s.io/kubernetes/pkg/api/v1/helper",
deps = [
"//pkg/api/helper:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",

View file

@ -88,18 +88,12 @@ func OpaqueIntResourceName(name string) v1.ResourceName {
var overcommitBlacklist = sets.NewString(string(v1.ResourceNvidiaGPU))
// IsOvercommitAllowed returns true if the resource is in the default
// namespace and not blacklisted and is not hugepages.
// namespace and not blacklisted.
func IsOvercommitAllowed(name v1.ResourceName) bool {
return IsDefaultNamespaceResource(name) &&
!IsHugePageResourceName(name) &&
!overcommitBlacklist.Has(string(name))
}
// Extended and Hugepages resources
func IsScalarResourceName(name v1.ResourceName) bool {
return IsExtendedResourceName(name) || IsHugePageResourceName(name)
}
// this function aims to check if the service's ClusterIP is set or not
// the objective is not to perform validation here
func IsServiceIPSet(service *v1.Service) bool {

View file

@ -9,7 +9,6 @@ load(
go_library(
name = "go_default_library",
srcs = ["util.go"],
importpath = "k8s.io/kubernetes/pkg/api/v1/pod",
deps = [
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
@ -20,7 +19,6 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["util_test.go"],
importpath = "k8s.io/kubernetes/pkg/api/v1/pod",
library = ":go_default_library",
deps = [
"//vendor/k8s.io/api/core/v1:go_default_library",

View file

@ -5101,7 +5101,7 @@ func autoConvert_v1_Taint_To_api_Taint(in *v1.Taint, out *api.Taint, s conversio
out.Key = in.Key
out.Value = in.Value
out.Effect = api.TaintEffect(in.Effect)
out.TimeAdded = (*meta_v1.Time)(unsafe.Pointer(in.TimeAdded))
out.TimeAdded = in.TimeAdded
return nil
}
@ -5114,7 +5114,7 @@ func autoConvert_api_Taint_To_v1_Taint(in *api.Taint, out *v1.Taint, s conversio
out.Key = in.Key
out.Value = in.Value
out.Effect = v1.TaintEffect(in.Effect)
out.TimeAdded = (*meta_v1.Time)(unsafe.Pointer(in.TimeAdded))
out.TimeAdded = in.TimeAdded
return nil
}

View file

@ -11,12 +11,12 @@ go_library(
"events.go",
"validation.go",
],
importpath = "k8s.io/kubernetes/pkg/api/validation",
visibility = ["//visibility:public"],
deps = [
"//pkg/api:go_default_library",
"//pkg/api/helper:go_default_library",
"//pkg/api/service:go_default_library",
"//pkg/api/util:go_default_library",
"//pkg/api/v1:go_default_library",
"//pkg/api/v1/helper:go_default_library",
"//pkg/capabilities:go_default_library",
@ -47,7 +47,6 @@ go_test(
"events_test.go",
"validation_test.go",
],
importpath = "k8s.io/kubernetes/pkg/api/validation",
library = ":go_default_library",
deps = [
"//pkg/api:go_default_library",

View file

@ -25,6 +25,7 @@ import (
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/kubernetes/pkg/api"
apiutil "k8s.io/kubernetes/pkg/api/util"
)
// ValidateEvent makes sure that the event makes sense.
@ -62,16 +63,12 @@ func ValidateEvent(event *api.Event) field.ErrorList {
// Check whether the kind in groupVersion is scoped at the root of the api hierarchy
func isNamespacedKind(kind, groupVersion string) (bool, error) {
gv, err := schema.ParseGroupVersion(groupVersion)
group := apiutil.GetGroup(groupVersion)
g, err := api.Registry.Group(group)
if err != nil {
return false, err
}
g, err := api.Registry.Group(gv.Group)
if err != nil {
return false, err
}
restMapping, err := g.RESTMapper.RESTMapping(schema.GroupKind{Group: gv.Group, Kind: kind}, gv.Version)
restMapping, err := g.RESTMapper.RESTMapping(schema.GroupKind{Group: group, Kind: kind}, apiutil.GetVersion(groupVersion))
if err != nil {
return false, err
}

View file

@ -1923,7 +1923,11 @@ func ValidateVolumeMounts(mounts []api.VolumeMount, volumes sets.String, contain
allErrs = append(allErrs, field.Invalid(idxPath.Child("mountPath"), mnt.MountPath, "must be unique"))
}
if !path.IsAbs(mnt.MountPath) {
allErrs = append(allErrs, field.Invalid(idxPath.Child("mountPath"), mnt.MountPath, "must be an absolute path"))
// also allow windows absolute path
p := mnt.MountPath
if len(p) < 2 || ((p[0] < 'A' || p[0] > 'Z') && (p[0] < 'a' || p[0] > 'z')) || p[1] != ':' {
allErrs = append(allErrs, field.Invalid(idxPath.Child("mountPath"), mnt.MountPath, "must be an absolute path"))
}
}
mountpoints.Insert(mnt.MountPath)
if len(mnt.SubPath) > 0 {
@ -3148,22 +3152,6 @@ func ValidateService(service *api.Service) field.ErrorList {
ports[key] = true
}
// Check for duplicate TargetPort
portsPath = specPath.Child("ports")
targetPorts := make(map[api.ServicePort]bool)
for i, port := range service.Spec.Ports {
if (port.TargetPort.Type == intstr.Int && port.TargetPort.IntVal == 0) || (port.TargetPort.Type == intstr.String && port.TargetPort.StrVal == "") {
continue
}
portPath := portsPath.Index(i)
key := api.ServicePort{Protocol: port.Protocol, TargetPort: port.TargetPort}
_, found := targetPorts[key]
if found {
allErrs = append(allErrs, field.Duplicate(portPath.Child("targetPort"), port.TargetPort))
}
targetPorts[key] = true
}
// Validate SourceRange field and annotation
_, ok := service.Annotations[api.AnnotationLoadBalancerSourceRangesKey]
if len(service.Spec.LoadBalancerSourceRanges) > 0 || ok {

View file

@ -3059,12 +3059,12 @@ func TestValidatePorts(t *testing.T) {
"invalid protocol case": {
[]api.ContainerPort{{ContainerPort: 80, Protocol: "tcp"}},
field.ErrorTypeNotSupported,
"protocol", `supported values: "TCP", "UDP"`,
"protocol", "supported values: TCP, UDP",
},
"invalid protocol": {
[]api.ContainerPort{{ContainerPort: 80, Protocol: "ICMP"}},
field.ErrorTypeNotSupported,
"protocol", `supported values: "TCP", "UDP"`,
"protocol", "supported values: TCP, UDP",
},
"protocol required": {
[]api.ContainerPort{{Name: "abc", ContainerPort: 80}},
@ -3426,7 +3426,7 @@ func TestValidateEnv(t *testing.T) {
},
},
}},
expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.labels": supported values: "metadata.name", "metadata.namespace", "metadata.uid", "spec.nodeName", "spec.serviceAccountName", "status.hostIP", "status.podIP"`,
expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.labels": supported values: metadata.name, metadata.namespace, metadata.uid, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP`,
},
{
name: "invalid fieldPath annotations",
@ -3439,7 +3439,7 @@ func TestValidateEnv(t *testing.T) {
},
},
}},
expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.annotations": supported values: "metadata.name", "metadata.namespace", "metadata.uid", "spec.nodeName", "spec.serviceAccountName", "status.hostIP", "status.podIP"`,
expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.annotations": supported values: metadata.name, metadata.namespace, metadata.uid, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP`,
},
{
name: "unsupported fieldPath",
@ -3452,7 +3452,7 @@ func TestValidateEnv(t *testing.T) {
},
},
}},
expectedError: `valueFrom.fieldRef.fieldPath: Unsupported value: "status.phase": supported values: "metadata.name", "metadata.namespace", "metadata.uid", "spec.nodeName", "spec.serviceAccountName", "status.hostIP", "status.podIP"`,
expectedError: `valueFrom.fieldRef.fieldPath: Unsupported value: "status.phase": supported values: metadata.name, metadata.namespace, metadata.uid, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP`,
},
}
for _, tc := range errorCases {
@ -5036,7 +5036,7 @@ func TestValidatePod(t *testing.T) {
Name: "pod-forgiveness-invalid",
Namespace: "ns",
},
Spec: extendPodSpecwithTolerations(validPodSpec(nil), []api.Toleration{{Key: "node.kubernetes.io/not-ready", Operator: "Exists", Effect: "NoExecute", TolerationSeconds: &[]int64{-2}[0]}}),
Spec: extendPodSpecwithTolerations(validPodSpec(nil), []api.Toleration{{Key: "node.alpha.kubernetes.io/notReady", Operator: "Exists", Effect: "NoExecute", TolerationSeconds: &[]int64{-2}[0]}}),
},
{ // docker default seccomp profile
ObjectMeta: metav1.ObjectMeta{
@ -5594,7 +5594,7 @@ func TestValidatePod(t *testing.T) {
Name: "pod-forgiveness-invalid",
Namespace: "ns",
},
Spec: extendPodSpecwithTolerations(validPodSpec(nil), []api.Toleration{{Key: "node.kubernetes.io/not-ready", Operator: "Exists", Effect: "NoSchedule", TolerationSeconds: &[]int64{20}[0]}}),
Spec: extendPodSpecwithTolerations(validPodSpec(nil), []api.Toleration{{Key: "node.alpha.kubernetes.io/notReady", Operator: "Exists", Effect: "NoSchedule", TolerationSeconds: &[]int64{20}[0]}}),
},
},
"must be a valid pod seccomp profile": {
@ -7050,42 +7050,6 @@ func TestValidateService(t *testing.T) {
},
numErrs: 0,
},
{
name: "invalid duplicate targetports (number with same protocol)",
tweakSvc: func(s *api.Service) {
s.Spec.Type = api.ServiceTypeClusterIP
s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "q", Port: 1, Protocol: "TCP", TargetPort: intstr.FromInt(8080)})
s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "r", Port: 2, Protocol: "TCP", TargetPort: intstr.FromInt(8080)})
},
numErrs: 1,
},
{
name: "invalid duplicate targetports (name with same protocol)",
tweakSvc: func(s *api.Service) {
s.Spec.Type = api.ServiceTypeClusterIP
s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "q", Port: 1, Protocol: "TCP", TargetPort: intstr.FromString("http")})
s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "r", Port: 2, Protocol: "TCP", TargetPort: intstr.FromString("http")})
},
numErrs: 1,
},
{
name: "valid duplicate targetports (number with different protocols)",
tweakSvc: func(s *api.Service) {
s.Spec.Type = api.ServiceTypeClusterIP
s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "q", Port: 1, Protocol: "TCP", TargetPort: intstr.FromInt(8080)})
s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "r", Port: 2, Protocol: "UDP", TargetPort: intstr.FromInt(8080)})
},
numErrs: 0,
},
{
name: "valid duplicate targetports (name with different protocols)",
tweakSvc: func(s *api.Service) {
s.Spec.Type = api.ServiceTypeClusterIP
s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "q", Port: 1, Protocol: "TCP", TargetPort: intstr.FromString("http")})
s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "r", Port: 2, Protocol: "UDP", TargetPort: intstr.FromString("http")})
},
numErrs: 0,
},
{
name: "valid type - cluster",
tweakSvc: func(s *api.Service) {

View file

@ -5903,15 +5903,7 @@ func (in *TCPSocketAction) DeepCopy() *TCPSocketAction {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Taint) DeepCopyInto(out *Taint) {
*out = *in
if in.TimeAdded != nil {
in, out := &in.TimeAdded, &out.TimeAdded
if *in == nil {
*out = nil
} else {
*out = new(v1.Time)
(*in).DeepCopyInto(*out)
}
}
in.TimeAdded.DeepCopyInto(&out.TimeAdded)
return
}

View file

@ -9,7 +9,6 @@ load(
go_test(
name = "go_default_test",
srcs = ["helpers_test.go"],
importpath = "k8s.io/kubernetes/pkg/apis/extensions",
library = ":go_default_library",
)
@ -22,7 +21,6 @@ go_library(
"types.go",
"zz_generated.deepcopy.go",
],
importpath = "k8s.io/kubernetes/pkg/apis/extensions",
deps = [
"//pkg/api:go_default_library",
"//pkg/apis/networking:go_default_library",

View file

@ -759,7 +759,7 @@ type IngressBackend struct {
// +genclient:method=UpdateScale,verb=update,subresource=scale,input=Scale,result=Scale
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ReplicaSet ensures that a specified number of pod replicas are running at any given time.
// ReplicaSet represents the configuration of a replica set.
type ReplicaSet struct {
metav1.TypeMeta
// +optional

View file

@ -13,7 +13,6 @@ go_library(
"types.go",
"zz_generated.deepcopy.go",
],
importpath = "k8s.io/kubernetes/pkg/apis/networking",
deps = [
"//pkg/api:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",

View file

@ -1,5 +1,4 @@
reviewers:
- caseydavenport
- cmluciano
- danwinship
- thockin

View file

@ -12,14 +12,13 @@ go_library(
"capabilities.go",
"doc.go",
],
importpath = "k8s.io/kubernetes/pkg/capabilities",
)
go_test(
name = "go_default_test",
srcs = ["capabilities_test.go"],
importpath = "k8s.io/kubernetes/pkg/capabilities",
library = ":go_default_library",
tags = ["automanaged"],
)
filegroup(

View file

@ -12,7 +12,6 @@ go_library(
"doc.go",
"plugins.go",
],
importpath = "k8s.io/kubernetes/pkg/cloudprovider",
deps = [
"//pkg/controller:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",

View file

@ -1,7 +1,5 @@
approvers:
- mikedanese
- dims
- wlan0
reviewers:
- thockin
- lavalamp
@ -36,8 +34,8 @@ reviewers:
- jszczepkowski
- markturansky
- girishkalele
- satnam6502
- jdef
- freehan
- jingxu97
- wlan0
- cheftako

View file

@ -4,7 +4,7 @@
The mechanism for supporting cloud providers is currently in transition: the original method of implementing cloud provider-specific functionality within the main kubernetes tree (here) is no longer advised; however, the proposed solution is still in development.
#### Guidance for potential cloud providers:
* Support for cloud providers is currently in a state of flux. Background information on motivation and the proposal for improving is in the github [proposal](https://git.k8s.io/community/contributors/design-proposals/cloud-provider/cloud-provider-refactoring.md).
* Support for cloud providers is currently in a state of flux. Background information on motivation and the proposal for improving is in the github [proposal](https://git.k8s.io/community/contributors/design-proposals/cloud-provider-refactoring.md).
* In support of this plan, a new cloud-controller-manager binary was added in 1.6. This was the first of several steps (see the proposal for more information).
* Attempts to contribute new cloud providers or (to a lesser extent) persistent volumes to the core repo will likely meet with some pushback from reviewers/approvers.
* It is understood that this is an unfortunate situation in which 'the old way is no longer supported but the new way is not ready yet', but the initial path is unsustainable, and contributors are encouraged to participate in the implementation of the proposed long-term solution, as there is risk that PRs for new cloud providers here will not be approved.
@ -13,4 +13,4 @@ The mechanism for supporting cloud providers is currently in transition: the or
#### Some additional context on status / direction:
* 1.6 added a new cloud-controller-manager binary that may be used for testing the new out-of-core cloudprovider flow.
* Setting cloud-provider=external allows for creation of a separate controller-manager binary
* 1.7 adds [extensible admission control](https://git.k8s.io/community/contributors/design-proposals/api-machinery/admission_control_extension.md), further enabling topology customization.
* 1.7 adds [extensible admission control](https://git.k8s.io/community/contributors/design-proposals/admission_control_extension.md), further enabling topology customization.

View file

@ -176,7 +176,6 @@ type Routes interface {
var (
InstanceNotFound = errors.New("instance not found")
DiskNotFound = errors.New("disk is not found")
NotImplemented = errors.New("unimplemented")
)
// Zone represents the location of a particular machine.

View file

@ -12,7 +12,6 @@ go_test(
"controller_ref_manager_test.go",
"controller_utils_test.go",
],
importpath = "k8s.io/kubernetes/pkg/controller",
library = ":go_default_library",
deps = [
"//pkg/api:go_default_library",
@ -20,7 +19,6 @@ go_test(
"//pkg/api/testapi:go_default_library",
"//pkg/controller/testutil:go_default_library",
"//pkg/securitycontext:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
@ -50,7 +48,6 @@ go_library(
"doc.go",
"lookup_cache.go",
],
importpath = "k8s.io/kubernetes/pkg/controller",
deps = [
"//pkg/api:go_default_library",
"//pkg/api/install:go_default_library",

View file

@ -22,6 +22,7 @@ import (
"math"
"math/rand"
"net/http/httptest"
"reflect"
"sort"
"sync"
"testing"
@ -46,8 +47,6 @@ import (
"k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/controller/testutil"
"k8s.io/kubernetes/pkg/securitycontext"
"github.com/stretchr/testify/assert"
)
// NewFakeControllerExpectationsLookup creates a fake store for PodExpectations.
@ -172,8 +171,9 @@ func TestControllerExpectations(t *testing.T) {
// RC fires off adds and deletes at apiserver, then sets expectations
rcKey, err := KeyFunc(rc)
assert.NoError(t, err, "Couldn't get key for object %#v: %v", rc, err)
if err != nil {
t.Errorf("Couldn't get key for object %#v: %v", rc, err)
}
e.SetExpectations(rcKey, adds, dels)
var wg sync.WaitGroup
for i := 0; i < adds+1; i++ {
@ -188,8 +188,9 @@ func TestControllerExpectations(t *testing.T) {
wg.Wait()
// There are still delete expectations
assert.False(t, e.SatisfiedExpectations(rcKey), "Rc will sync before expectations are met")
if e.SatisfiedExpectations(rcKey) {
t.Errorf("Rc will sync before expectations are met")
}
for i := 0; i < dels+1; i++ {
wg.Add(1)
go func() {
@ -200,29 +201,34 @@ func TestControllerExpectations(t *testing.T) {
wg.Wait()
// Expectations have been surpassed
podExp, exists, err := e.GetExpectations(rcKey)
assert.NoError(t, err, "Could not get expectations for rc, exists %v and err %v", exists, err)
assert.True(t, exists, "Could not get expectations for rc, exists %v and err %v", exists, err)
add, del := podExp.GetExpectations()
assert.Equal(t, int64(-1), add, "Unexpected pod expectations %#v", podExp)
assert.Equal(t, int64(-1), del, "Unexpected pod expectations %#v", podExp)
assert.True(t, e.SatisfiedExpectations(rcKey), "Expectations are met but the rc will not sync")
if podExp, exists, err := e.GetExpectations(rcKey); err == nil && exists {
add, del := podExp.GetExpectations()
if add != -1 || del != -1 {
t.Errorf("Unexpected pod expectations %#v", podExp)
}
} else {
t.Errorf("Could not get expectations for rc, exists %v and err %v", exists, err)
}
if !e.SatisfiedExpectations(rcKey) {
t.Errorf("Expectations are met but the rc will not sync")
}
// Next round of rc sync, old expectations are cleared
e.SetExpectations(rcKey, 1, 2)
podExp, exists, err = e.GetExpectations(rcKey)
assert.NoError(t, err, "Could not get expectations for rc, exists %v and err %v", exists, err)
assert.True(t, exists, "Could not get expectations for rc, exists %v and err %v", exists, err)
add, del = podExp.GetExpectations()
assert.Equal(t, int64(1), add, "Unexpected pod expectations %#v", podExp)
assert.Equal(t, int64(2), del, "Unexpected pod expectations %#v", podExp)
if podExp, exists, err := e.GetExpectations(rcKey); err == nil && exists {
add, del := podExp.GetExpectations()
if add != 1 || del != 2 {
t.Errorf("Unexpected pod expectations %#v", podExp)
}
} else {
t.Errorf("Could not get expectations for rc, exists %v and err %v", exists, err)
}
// Expectations have expired because of ttl
fakeClock.Step(ttl + 1)
assert.True(t, e.SatisfiedExpectations(rcKey),
"Expectations should have expired but didn't")
if !e.SatisfiedExpectations(rcKey) {
t.Errorf("Expectations should have expired but didn't")
}
}
func TestUIDExpectations(t *testing.T) {
@ -260,20 +266,19 @@ func TestUIDExpectations(t *testing.T) {
rcKeys[i], rcKeys[j] = rcKeys[j], rcKeys[i]
}
for _, rcKey := range rcKeys {
assert.False(t, uidExp.SatisfiedExpectations(rcKey),
"Controller %v satisfied expectations before deletion", rcKey)
if uidExp.SatisfiedExpectations(rcKey) {
t.Errorf("Controller %v satisfied expectations before deletion", rcKey)
}
for _, p := range rcToPods[rcKey] {
uidExp.DeletionObserved(rcKey, p)
}
assert.True(t, uidExp.SatisfiedExpectations(rcKey),
"Controller %v didn't satisfy expectations after deletion", rcKey)
if !uidExp.SatisfiedExpectations(rcKey) {
t.Errorf("Controller %v didn't satisfy expectations after deletion", rcKey)
}
uidExp.DeleteExpectations(rcKey)
assert.Nil(t, uidExp.GetUIDs(rcKey),
"Failed to delete uid expectations for %v", rcKey)
if uidExp.GetUIDs(rcKey) != nil {
t.Errorf("Failed to delete uid expectations for %v", rcKey)
}
}
}
@ -296,8 +301,9 @@ func TestCreatePods(t *testing.T) {
controllerSpec := newReplicationController(1)
// Make sure createReplica sends a POST to the apiserver with a pod from the controllers pod template
err := podControl.CreatePods(ns, controllerSpec.Spec.Template, controllerSpec)
assert.NoError(t, err, "unexpected error: %v", err)
if err := podControl.CreatePods(ns, controllerSpec.Spec.Template, controllerSpec); err != nil {
t.Fatalf("unexpected error: %v", err)
}
expectedPod := v1.Pod{
ObjectMeta: metav1.ObjectMeta{
@ -308,10 +314,14 @@ func TestCreatePods(t *testing.T) {
}
fakeHandler.ValidateRequest(t, testapi.Default.ResourcePath("pods", metav1.NamespaceDefault, ""), "POST", nil)
var actualPod = &v1.Pod{}
err = json.Unmarshal([]byte(fakeHandler.RequestBody), actualPod)
assert.NoError(t, err, "unexpected error: %v", err)
assert.True(t, apiequality.Semantic.DeepDerivative(&expectedPod, actualPod),
"Body: %s", fakeHandler.RequestBody)
err := json.Unmarshal([]byte(fakeHandler.RequestBody), actualPod)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if !apiequality.Semantic.DeepDerivative(&expectedPod, actualPod) {
t.Logf("Body: %s", fakeHandler.RequestBody)
t.Errorf("Unexpected mismatch. Expected\n %#v,\n Got:\n %#v", &expectedPod, actualPod)
}
}
func TestActivePodFiltering(t *testing.T) {
@ -334,11 +344,9 @@ func TestActivePodFiltering(t *testing.T) {
for _, pod := range got {
gotNames.Insert(pod.Name)
}
assert.Equal(t, 0, expectedNames.Difference(gotNames).Len(),
"expected %v, got %v", expectedNames.List(), gotNames.List())
assert.Equal(t, 0, gotNames.Difference(expectedNames).Len(),
"expected %v, got %v", expectedNames.List(), gotNames.List())
if expectedNames.Difference(gotNames).Len() != 0 || gotNames.Difference(expectedNames).Len() != 0 {
t.Errorf("expected %v, got %v", expectedNames.List(), gotNames.List())
}
}
func TestSortingActivePods(t *testing.T) {
@ -412,7 +420,9 @@ func TestSortingActivePods(t *testing.T) {
sort.Sort(ActivePods(randomizedPods))
actual := getOrder(randomizedPods)
assert.EqualValues(t, expected, actual, "expected %v, got %v", expected, actual)
if !reflect.DeepEqual(actual, expected) {
t.Errorf("expected %v, got %v", expected, actual)
}
}
}
@ -433,10 +443,9 @@ func TestActiveReplicaSetsFiltering(t *testing.T) {
gotNames.Insert(rs.Name)
}
assert.Equal(t, 0, expectedNames.Difference(gotNames).Len(),
"expected %v, got %v", expectedNames.List(), gotNames.List())
assert.Equal(t, 0, gotNames.Difference(expectedNames).Len(),
"expected %v, got %v", expectedNames.List(), gotNames.List())
if expectedNames.Difference(gotNames).Len() != 0 || gotNames.Difference(expectedNames).Len() != 0 {
t.Errorf("expected %v, got %v", expectedNames.List(), gotNames.List())
}
}
func int64P(num int64) *int64 {
@ -471,7 +480,9 @@ func TestComputeHash(t *testing.T) {
hash := ComputeHash(test.template, test.collisionCount)
otherHash := ComputeHash(test.template, test.otherCollisionCount)
assert.NotEqual(t, hash, otherHash, "expected different hashes but got the same: %d", hash)
if hash == otherHash {
t.Errorf("expected different hashes but got the same: %d", hash)
}
}
}
@ -635,17 +646,20 @@ func TestRemoveTaintOffNode(t *testing.T) {
}
for _, test := range tests {
node, _ := test.nodeHandler.Get(test.nodeName, metav1.GetOptions{})
err := RemoveTaintOffNode(test.nodeHandler, test.nodeName, node, test.taintsToRemove...)
assert.NoError(t, err, "%s: RemoveTaintOffNode() error = %v", test.name, err)
if err := RemoveTaintOffNode(test.nodeHandler, test.nodeName, node, test.taintsToRemove...); err != nil {
t.Errorf("%s: RemoveTaintOffNode() error = %v", test.name, err)
}
node, _ = test.nodeHandler.Get(test.nodeName, metav1.GetOptions{})
assert.EqualValues(t, test.expectedTaints, node.Spec.Taints,
"%s: failed to remove taint off node: expected %+v, got %+v",
test.name, test.expectedTaints, node.Spec.Taints)
if !reflect.DeepEqual(node.Spec.Taints, test.expectedTaints) {
t.Errorf("%s: failed to remove taint off node: expected %+v, got %+v",
test.name, test.expectedTaints, node.Spec.Taints)
}
assert.Equal(t, test.requestCount, test.nodeHandler.RequestCount,
"%s: unexpected request count: expected %+v, got %+v",
test.name, test.requestCount, test.nodeHandler.RequestCount)
if test.nodeHandler.RequestCount != test.requestCount {
t.Errorf("%s: unexpected request count: expected %+v, got %+v",
test.name, test.requestCount, test.nodeHandler.RequestCount)
}
}
}
@ -810,16 +824,19 @@ func TestAddOrUpdateTaintOnNode(t *testing.T) {
},
}
for _, test := range tests {
err := AddOrUpdateTaintOnNode(test.nodeHandler, test.nodeName, test.taintsToAdd...)
assert.NoError(t, err, "%s: AddOrUpdateTaintOnNode() error = %v", test.name, err)
if err := AddOrUpdateTaintOnNode(test.nodeHandler, test.nodeName, test.taintsToAdd...); err != nil {
t.Errorf("%s: AddOrUpdateTaintOnNode() error = %v", test.name, err)
}
node, _ := test.nodeHandler.Get(test.nodeName, metav1.GetOptions{})
assert.EqualValues(t, test.expectedTaints, node.Spec.Taints,
"%s: failed to add taint to node: expected %+v, got %+v",
test.name, test.expectedTaints, node.Spec.Taints)
if !reflect.DeepEqual(node.Spec.Taints, test.expectedTaints) {
t.Errorf("%s: failed to add taint to node: expected %+v, got %+v",
test.name, test.expectedTaints, node.Spec.Taints)
}
assert.Equal(t, test.requestCount, test.nodeHandler.RequestCount,
"%s: unexpected request count: expected %+v, got %+v",
test.name, test.requestCount, test.nodeHandler.RequestCount)
if test.nodeHandler.RequestCount != test.requestCount {
t.Errorf("%s: unexpected request count: expected %+v, got %+v",
test.name, test.requestCount, test.nodeHandler.RequestCount)
}
}
}

View file

@ -8,7 +8,6 @@ load(
go_library(
name = "go_default_library",
srcs = ["kube_features.go"],
importpath = "k8s.io/kubernetes/pkg/features",
deps = [
"//vendor/k8s.io/apiextensions-apiserver/pkg/features:go_default_library",
"//vendor/k8s.io/apiserver/pkg/features:go_default_library",

View file

@ -163,6 +163,12 @@ const (
//
// Enable pods to consume pre-allocated huge pages of varying page sizes
HugePages utilfeature.Feature = "HugePages"
// owner @brendandburns
// alpha: v1.8
//
// Enable nodes to exclude themselves from service load balancers
ServiceNodeExclusion utilfeature.Feature = "ServiceNodeExclusion"
)
func init() {
@ -194,6 +200,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS
MountPropagation: {Default: false, PreRelease: utilfeature.Alpha},
ExpandPersistentVolumes: {Default: false, PreRelease: utilfeature.Alpha},
CPUManager: {Default: false, PreRelease: utilfeature.Alpha},
ServiceNodeExclusion: {Default: false, PreRelease: utilfeature.Alpha},
// inherited features from generic apiserver, relisted here to get a conflict if it is changed
// unintentionally on either side:
@ -201,7 +208,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS
genericfeatures.AdvancedAuditing: {Default: true, PreRelease: utilfeature.Beta},
genericfeatures.APIResponseCompression: {Default: false, PreRelease: utilfeature.Alpha},
genericfeatures.Initializers: {Default: false, PreRelease: utilfeature.Alpha},
genericfeatures.APIListChunking: {Default: true, PreRelease: utilfeature.Beta},
genericfeatures.APIListChunking: {Default: false, PreRelease: utilfeature.Alpha},
// inherited features from apiextensions-apiserver, relisted here to get a conflict if it is changed
// unintentionally on either side:

View file

@ -28,8 +28,8 @@ go_library(
"util.go",
"volume_host.go",
],
importpath = "k8s.io/kubernetes/pkg/kubelet",
deps = [
"//cmd/kubelet/app/options:go_default_library",
"//pkg/api:go_default_library",
"//pkg/api/v1:go_default_library",
"//pkg/api/v1/helper:go_default_library",
@ -116,6 +116,7 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
@ -129,12 +130,12 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
"//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library",
"//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
"//vendor/k8s.io/client-go/listers/core/v1:go_default_library",
"//vendor/k8s.io/client-go/tools/cache:go_default_library",
"//vendor/k8s.io/client-go/tools/record:go_default_library",
"//vendor/k8s.io/client-go/tools/remotecommand:go_default_library",
"//vendor/k8s.io/client-go/util/certificate:go_default_library",
"//vendor/k8s.io/client-go/util/flowcontrol:go_default_library",
"//vendor/k8s.io/client-go/util/integer:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
@ -164,7 +165,6 @@ go_test(
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/kubelet",
library = ":go_default_library",
deps = [
"//pkg/api:go_default_library",
@ -288,7 +288,6 @@ filegroup(
"//pkg/kubelet/types:all-srcs",
"//pkg/kubelet/util:all-srcs",
"//pkg/kubelet/volumemanager:all-srcs",
"//pkg/kubelet/winstats:all-srcs",
],
tags = ["automanaged"],
)

View file

@ -11,7 +11,6 @@ go_library(
"well_known_annotations.go",
"well_known_labels.go",
],
importpath = "k8s.io/kubernetes/pkg/kubelet/apis",
)
filegroup(

View file

@ -8,7 +8,6 @@ load(
go_library(
name = "go_default_library",
srcs = ["services.go"],
importpath = "k8s.io/kubernetes/pkg/kubelet/apis/cri",
deps = ["//pkg/kubelet/apis/cri/v1alpha1/runtime:go_default_library"],
)

View file

@ -11,7 +11,6 @@ go_library(
"api.pb.go",
"constants.go",
],
importpath = "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime",
deps = [
"//vendor/github.com/gogo/protobuf/gogoproto:go_default_library",
"//vendor/github.com/gogo/protobuf/proto:go_default_library",

View file

@ -1397,7 +1397,6 @@ type LinuxContainerSecurityContext struct {
SupplementalGroups []int64 `protobuf:"varint,8,rep,packed,name=supplemental_groups,json=supplementalGroups" json:"supplemental_groups,omitempty"`
// AppArmor profile for the container, candidate values are:
// * runtime/default: equivalent to not specifying a profile.
// * unconfined: no profiles are loaded
// * localhost/<profile_name>: profile loaded on the node
// (localhost) by name. The possible profile names are detailed at
// http://wiki.apparmor.net/index.php/AppArmor_Core_Policy_Reference
@ -2377,17 +2376,7 @@ type ExecRequest struct {
// Whether to exec the command in a TTY.
Tty bool `protobuf:"varint,3,opt,name=tty,proto3" json:"tty,omitempty"`
// Whether to stream stdin.
// One of `stdin`, `stdout`, and `stderr` MUST be true.
Stdin bool `protobuf:"varint,4,opt,name=stdin,proto3" json:"stdin,omitempty"`
// Whether to stream stdout.
// One of `stdin`, `stdout`, and `stderr` MUST be true.
Stdout bool `protobuf:"varint,5,opt,name=stdout,proto3" json:"stdout,omitempty"`
// Whether to stream stderr.
// One of `stdin`, `stdout`, and `stderr` MUST be true.
// If `tty` is true, `stderr` MUST be false. Multiplexing is not supported
// in this case. The output of stdout and stderr will be combined to a
// single stream.
Stderr bool `protobuf:"varint,6,opt,name=stderr,proto3" json:"stderr,omitempty"`
}
func (m *ExecRequest) Reset() { *m = ExecRequest{} }
@ -2422,20 +2411,6 @@ func (m *ExecRequest) GetStdin() bool {
return false
}
func (m *ExecRequest) GetStdout() bool {
if m != nil {
return m.Stdout
}
return false
}
func (m *ExecRequest) GetStderr() bool {
if m != nil {
return m.Stderr
}
return false
}
type ExecResponse struct {
// Fully qualified URL of the exec streaming server.
Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
@ -2456,20 +2431,10 @@ type AttachRequest struct {
// ID of the container to which to attach.
ContainerId string `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"`
// Whether to stream stdin.
// One of `stdin`, `stdout`, and `stderr` MUST be true.
Stdin bool `protobuf:"varint,2,opt,name=stdin,proto3" json:"stdin,omitempty"`
// Whether the process being attached is running in a TTY.
// This must match the TTY setting in the ContainerConfig.
Tty bool `protobuf:"varint,3,opt,name=tty,proto3" json:"tty,omitempty"`
// Whether to stream stdout.
// One of `stdin`, `stdout`, and `stderr` MUST be true.
Stdout bool `protobuf:"varint,4,opt,name=stdout,proto3" json:"stdout,omitempty"`
// Whether to stream stderr.
// One of `stdin`, `stdout`, and `stderr` MUST be true.
// If `tty` is true, `stderr` MUST be false. Multiplexing is not supported
// in this case. The output of stdout and stderr will be combined to a
// single stream.
Stderr bool `protobuf:"varint,5,opt,name=stderr,proto3" json:"stderr,omitempty"`
}
func (m *AttachRequest) Reset() { *m = AttachRequest{} }
@ -2497,20 +2462,6 @@ func (m *AttachRequest) GetTty() bool {
return false
}
func (m *AttachRequest) GetStdout() bool {
if m != nil {
return m.Stdout
}
return false
}
func (m *AttachRequest) GetStderr() bool {
if m != nil {
return m.Stderr
}
return false
}
type AttachResponse struct {
// Fully qualified URL of the attach streaming server.
Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
@ -7070,26 +7021,6 @@ func (m *ExecRequest) MarshalTo(dAtA []byte) (int, error) {
}
i++
}
if m.Stdout {
dAtA[i] = 0x28
i++
if m.Stdout {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i++
}
if m.Stderr {
dAtA[i] = 0x30
i++
if m.Stderr {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i++
}
return i, nil
}
@ -7158,26 +7089,6 @@ func (m *AttachRequest) MarshalTo(dAtA []byte) (int, error) {
}
i++
}
if m.Stdout {
dAtA[i] = 0x20
i++
if m.Stdout {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i++
}
if m.Stderr {
dAtA[i] = 0x28
i++
if m.Stderr {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i++
}
return i, nil
}
@ -9506,12 +9417,6 @@ func (m *ExecRequest) Size() (n int) {
if m.Stdin {
n += 2
}
if m.Stdout {
n += 2
}
if m.Stderr {
n += 2
}
return n
}
@ -9538,12 +9443,6 @@ func (m *AttachRequest) Size() (n int) {
if m.Tty {
n += 2
}
if m.Stdout {
n += 2
}
if m.Stderr {
n += 2
}
return n
}
@ -10892,8 +10791,6 @@ func (this *ExecRequest) String() string {
`Cmd:` + fmt.Sprintf("%v", this.Cmd) + `,`,
`Tty:` + fmt.Sprintf("%v", this.Tty) + `,`,
`Stdin:` + fmt.Sprintf("%v", this.Stdin) + `,`,
`Stdout:` + fmt.Sprintf("%v", this.Stdout) + `,`,
`Stderr:` + fmt.Sprintf("%v", this.Stderr) + `,`,
`}`,
}, "")
return s
@ -10916,8 +10813,6 @@ func (this *AttachRequest) String() string {
`ContainerId:` + fmt.Sprintf("%v", this.ContainerId) + `,`,
`Stdin:` + fmt.Sprintf("%v", this.Stdin) + `,`,
`Tty:` + fmt.Sprintf("%v", this.Tty) + `,`,
`Stdout:` + fmt.Sprintf("%v", this.Stdout) + `,`,
`Stderr:` + fmt.Sprintf("%v", this.Stderr) + `,`,
`}`,
}, "")
return s
@ -20438,46 +20333,6 @@ func (m *ExecRequest) Unmarshal(dAtA []byte) error {
}
}
m.Stdin = bool(v != 0)
case 5:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Stdout", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowApi
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.Stdout = bool(v != 0)
case 6:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Stderr", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowApi
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.Stderr = bool(v != 0)
default:
iNdEx = preIndex
skippy, err := skipApi(dAtA[iNdEx:])
@ -20676,46 +20531,6 @@ func (m *AttachRequest) Unmarshal(dAtA []byte) error {
}
}
m.Tty = bool(v != 0)
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Stdout", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowApi
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.Stdout = bool(v != 0)
case 5:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Stderr", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowApi
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.Stderr = bool(v != 0)
default:
iNdEx = preIndex
skippy, err := skipApi(dAtA[iNdEx:])
@ -24753,274 +24568,273 @@ var (
func init() { proto.RegisterFile("api.proto", fileDescriptorApi) }
var fileDescriptorApi = []byte{
// 4300 bytes of a gzipped FileDescriptorProto
// 4276 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x3b, 0x4d, 0x6f, 0x1b, 0x49,
0x76, 0x22, 0xa9, 0x0f, 0xf2, 0x51, 0xa4, 0xa8, 0x92, 0x2c, 0x51, 0xb4, 0x2d, 0xcb, 0xed, 0xf1,
0x8c, 0xed, 0x5d, 0x7b, 0x3c, 0x9a, 0x1d, 0x4f, 0xc6, 0xf3, 0x65, 0x8e, 0x24, 0x3b, 0x1a, 0xdb,
0x94, 0xb6, 0x29, 0xcd, 0xee, 0x62, 0x03, 0x74, 0x5a, 0xec, 0x12, 0xd5, 0x33, 0x64, 0x77, 0x4f,
0x77, 0xb5, 0x6d, 0x05, 0x39, 0x24, 0x97, 0x20, 0x08, 0x10, 0x60, 0x73, 0x4c, 0x4e, 0x39, 0x04,
0x58, 0xe4, 0x92, 0x43, 0x0e, 0x41, 0x7e, 0x41, 0xb0, 0x97, 0x05, 0x02, 0x04, 0x08, 0x92, 0x5b,
0xd6, 0x39, 0xe4, 0x10, 0x20, 0xbf, 0x21, 0xa8, 0xaf, 0xee, 0xea, 0x2f, 0x5a, 0xf2, 0x0c, 0x76,
0x7d, 0x62, 0xd7, 0xab, 0x57, 0xaf, 0x5e, 0xbd, 0xf7, 0xea, 0xd5, 0x7b, 0xaf, 0x8a, 0x50, 0x33,
0x3d, 0xfb, 0x8e, 0xe7, 0xbb, 0xc4, 0x45, 0x73, 0x7e, 0xe8, 0x10, 0x7b, 0x8c, 0x3b, 0xb7, 0x87,
0x36, 0x39, 0x09, 0x8f, 0xee, 0x0c, 0xdc, 0xf1, 0xbb, 0x43, 0x77, 0xe8, 0xbe, 0xcb, 0xfa, 0x8f,
0xc2, 0x63, 0xd6, 0x62, 0x0d, 0xf6, 0xc5, 0xc7, 0x69, 0xb7, 0xa0, 0xf9, 0x15, 0xf6, 0x03, 0xdb,
0x75, 0x74, 0xfc, 0x6d, 0x88, 0x03, 0x82, 0xda, 0x30, 0xf7, 0x8c, 0x43, 0xda, 0xa5, 0x8d, 0xd2,
0x8d, 0x9a, 0x2e, 0x9b, 0xda, 0x2f, 0x4b, 0xb0, 0x10, 0x21, 0x07, 0x9e, 0xeb, 0x04, 0xb8, 0x18,
0x1b, 0x5d, 0x85, 0x79, 0xc1, 0x93, 0xe1, 0x98, 0x63, 0xdc, 0x2e, 0xb3, 0xee, 0xba, 0x80, 0xf5,
0xcc, 0x31, 0x46, 0xef, 0xc0, 0x82, 0x44, 0x91, 0x44, 0x2a, 0x0c, 0xab, 0x29, 0xc0, 0x62, 0x36,
0x74, 0x07, 0x96, 0x24, 0xa2, 0xe9, 0xd9, 0x11, 0xf2, 0x34, 0x43, 0x5e, 0x14, 0x5d, 0x5d, 0xcf,
0x16, 0xf8, 0xda, 0xcf, 0xa1, 0xb6, 0xdd, 0xeb, 0x6f, 0xb9, 0xce, 0xb1, 0x3d, 0xa4, 0x2c, 0x06,
0xd8, 0xa7, 0x63, 0xda, 0xa5, 0x8d, 0x0a, 0x65, 0x51, 0x34, 0x51, 0x07, 0xaa, 0x01, 0x36, 0xfd,
0xc1, 0x09, 0x0e, 0xda, 0x65, 0xd6, 0x15, 0xb5, 0xe9, 0x28, 0xd7, 0x23, 0xb6, 0xeb, 0x04, 0xed,
0x0a, 0x1f, 0x25, 0x9a, 0xda, 0x5f, 0x97, 0xa0, 0xbe, 0xef, 0xfa, 0xe4, 0xa9, 0xe9, 0x79, 0xb6,
0x33, 0x44, 0xb7, 0xa1, 0xca, 0x64, 0x39, 0x70, 0x47, 0x4c, 0x06, 0xcd, 0xcd, 0xc5, 0x3b, 0x82,
0xa5, 0x3b, 0xfb, 0xa2, 0x43, 0x8f, 0x50, 0xd0, 0x75, 0x68, 0x0e, 0x5c, 0x87, 0x98, 0xb6, 0x83,
0x7d, 0xc3, 0x73, 0x7d, 0xc2, 0x24, 0x33, 0xa3, 0x37, 0x22, 0x28, 0x25, 0x8e, 0x2e, 0x42, 0xed,
0xc4, 0x0d, 0x08, 0xc7, 0xa8, 0x30, 0x8c, 0x2a, 0x05, 0xb0, 0xce, 0x55, 0x98, 0x63, 0x9d, 0xb6,
0x27, 0x64, 0x30, 0x4b, 0x9b, 0xbb, 0x9e, 0xf6, 0xeb, 0x12, 0xcc, 0x3c, 0x75, 0x43, 0x87, 0xa4,
0xa6, 0x31, 0xc9, 0x89, 0xd0, 0x8f, 0x32, 0x8d, 0x49, 0x4e, 0xe2, 0x69, 0x28, 0x06, 0x57, 0x11,
0x9f, 0x86, 0x76, 0x76, 0xa0, 0xea, 0x63, 0xd3, 0x72, 0x9d, 0xd1, 0x29, 0x63, 0xa1, 0xaa, 0x47,
0x6d, 0xaa, 0xbb, 0x00, 0x8f, 0x6c, 0x27, 0x7c, 0x61, 0xf8, 0x78, 0x64, 0x1e, 0xe1, 0x11, 0x63,
0xa5, 0xaa, 0x37, 0x05, 0x58, 0xe7, 0x50, 0xf4, 0x31, 0xd4, 0x3d, 0xdf, 0xf5, 0xcc, 0xa1, 0x49,
0xc5, 0xd7, 0x9e, 0x61, 0x12, 0x5a, 0x8b, 0x24, 0xc4, 0xb8, 0xdd, 0x8f, 0x11, 0x74, 0x15, 0x5b,
0xfb, 0x1a, 0x16, 0xa8, 0xa5, 0x04, 0x9e, 0x39, 0xc0, 0x7b, 0x4c, 0xfe, 0xd4, 0xae, 0x18, 0xc7,
0x0e, 0x26, 0xcf, 0x5d, 0xff, 0x1b, 0xb6, 0xac, 0xaa, 0x5e, 0xa7, 0xb0, 0x1e, 0x07, 0xa1, 0x35,
0xa8, 0xf2, 0x45, 0xd9, 0x16, 0x5b, 0x53, 0x55, 0x67, 0xe2, 0xda, 0xb7, 0xad, 0xa8, 0xcb, 0xf6,
0x06, 0x62, 0x49, 0x73, 0x5c, 0x74, 0x03, 0x4d, 0x03, 0xd8, 0x75, 0xc8, 0xbd, 0x1f, 0x7d, 0x65,
0x8e, 0x42, 0x8c, 0x96, 0x61, 0xe6, 0x19, 0xfd, 0x60, 0xf4, 0x2b, 0x3a, 0x6f, 0x68, 0x7f, 0x56,
0x81, 0x8b, 0x4f, 0xe8, 0xea, 0xfa, 0xa6, 0x63, 0x1d, 0xb9, 0x2f, 0xfa, 0x78, 0x10, 0xfa, 0x36,
0x39, 0xdd, 0x72, 0x1d, 0x82, 0x5f, 0x10, 0xb4, 0x03, 0x8b, 0x8e, 0xe4, 0xd7, 0x90, 0xf6, 0x43,
0x29, 0xd4, 0x37, 0xdb, 0xd1, 0x92, 0x53, 0x2b, 0xd2, 0x5b, 0x4e, 0x12, 0x10, 0xa0, 0xcf, 0x63,
0xe1, 0x4a, 0x22, 0x65, 0x46, 0x64, 0x25, 0x22, 0xd2, 0xdf, 0x61, 0x7c, 0x08, 0x12, 0x52, 0xe8,
0x92, 0xc0, 0xfb, 0x40, 0x37, 0x9a, 0x61, 0x06, 0x46, 0x18, 0x60, 0x9f, 0xad, 0xb4, 0xbe, 0xb9,
0x14, 0x0d, 0x8e, 0xd7, 0xa9, 0xd7, 0xfc, 0xd0, 0xe9, 0x06, 0x87, 0x01, 0xf6, 0xd9, 0x76, 0x14,
0xea, 0x35, 0x7c, 0xd7, 0x25, 0xc7, 0x81, 0x54, 0xa9, 0x04, 0xeb, 0x0c, 0x8a, 0xde, 0x85, 0xa5,
0x20, 0xf4, 0xbc, 0x11, 0x1e, 0x63, 0x87, 0x98, 0x23, 0x63, 0xe8, 0xbb, 0xa1, 0x17, 0xb4, 0x67,
0x36, 0x2a, 0x37, 0x2a, 0x3a, 0x52, 0xbb, 0x1e, 0xb1, 0x1e, 0xb4, 0x0e, 0xe0, 0xf9, 0xf6, 0x33,
0x7b, 0x84, 0x87, 0xd8, 0x6a, 0xcf, 0x32, 0xa2, 0x0a, 0x04, 0xdd, 0x85, 0xe5, 0x00, 0x0f, 0x06,
0xee, 0xd8, 0x33, 0x3c, 0xdf, 0x3d, 0xb6, 0x47, 0x98, 0x1b, 0xe4, 0x1c, 0x33, 0x48, 0x24, 0xfa,
0xf6, 0x79, 0x17, 0x35, 0x4d, 0xed, 0x17, 0x65, 0xb8, 0xc0, 0x04, 0xb0, 0xef, 0x5a, 0x42, 0x17,
0x62, 0xbb, 0x5f, 0x83, 0xc6, 0x80, 0x31, 0x64, 0x78, 0xa6, 0x8f, 0x1d, 0x22, 0xec, 0x7e, 0x9e,
0x03, 0xf7, 0x19, 0x0c, 0xed, 0x41, 0x2b, 0x10, 0xaa, 0x33, 0x06, 0x5c, 0x77, 0x42, 0xc2, 0x6f,
0x45, 0x42, 0x9a, 0xa0, 0x67, 0x7d, 0x21, 0xc8, 0x28, 0x7e, 0x2e, 0x38, 0x0d, 0x06, 0x64, 0xc4,
0xdd, 0x45, 0x7d, 0xf3, 0x07, 0x49, 0x3a, 0x69, 0x36, 0xef, 0xf4, 0x39, 0xf6, 0x8e, 0x43, 0xfc,
0x53, 0x5d, 0x8e, 0xed, 0xdc, 0x87, 0x79, 0xb5, 0x03, 0xb5, 0xa0, 0xf2, 0x0d, 0x3e, 0x15, 0x4b,
0xa0, 0x9f, 0xb1, 0x5d, 0xf2, 0xcd, 0xca, 0x1b, 0xf7, 0xcb, 0xbf, 0x57, 0xd2, 0x7c, 0x40, 0xf1,
0x2c, 0x4f, 0x31, 0x31, 0x2d, 0x93, 0x98, 0x08, 0xc1, 0x34, 0x73, 0xbf, 0x9c, 0x04, 0xfb, 0xa6,
0x54, 0x43, 0xb1, 0x35, 0x6a, 0x3a, 0xfd, 0x44, 0x97, 0xa0, 0x16, 0x19, 0xa1, 0xf0, 0xc1, 0x31,
0x80, 0xfa, 0x42, 0x93, 0x10, 0x3c, 0xf6, 0x08, 0x33, 0x88, 0x86, 0x2e, 0x9b, 0xda, 0x3f, 0x4f,
0x43, 0x2b, 0xa3, 0x81, 0x0f, 0xa1, 0x3a, 0x16, 0xd3, 0x0b, 0xdb, 0xbf, 0x18, 0x3b, 0xc4, 0x0c,
0x87, 0x7a, 0x84, 0x4c, 0xfd, 0x0d, 0xdd, 0x8c, 0xca, 0x71, 0x11, 0xb5, 0xa9, 0x5a, 0x47, 0xee,
0xd0, 0xb0, 0x6c, 0x1f, 0x0f, 0x88, 0xeb, 0x9f, 0x0a, 0x2e, 0xe7, 0x47, 0xee, 0x70, 0x5b, 0xc2,
0xd0, 0x7b, 0x00, 0x96, 0x13, 0x50, 0x8d, 0x1e, 0xdb, 0x43, 0xc6, 0x6b, 0x7d, 0x13, 0x45, 0x73,
0x47, 0x47, 0x82, 0x5e, 0xb3, 0x9c, 0x40, 0x30, 0xfb, 0x11, 0x34, 0xa8, 0x8b, 0x35, 0xc6, 0xdc,
0x9b, 0x73, 0x2b, 0xae, 0x6f, 0x2e, 0x2b, 0x1c, 0x47, 0xae, 0x5e, 0x9f, 0xf7, 0xe2, 0x46, 0x80,
0x3e, 0x85, 0x59, 0xe6, 0xe2, 0x82, 0xf6, 0x2c, 0x1b, 0x73, 0x3d, 0x67, 0x95, 0x42, 0xdb, 0x4f,
0x18, 0x1e, 0x57, 0xb6, 0x18, 0x84, 0x9e, 0x40, 0xdd, 0x74, 0x1c, 0x97, 0x98, 0x7c, 0x83, 0xcf,
0x31, 0x1a, 0xb7, 0x8a, 0x69, 0x74, 0x63, 0x64, 0x4e, 0x48, 0x1d, 0x8e, 0x7e, 0x04, 0x33, 0xcc,
0x03, 0xb4, 0xab, 0x6c, 0xd5, 0xeb, 0x93, 0xcd, 0x4f, 0xe7, 0xc8, 0x9d, 0x8f, 0xa0, 0xae, 0xb0,
0x76, 0x1e, 0x73, 0xeb, 0x7c, 0x06, 0xad, 0x34, 0x47, 0xe7, 0x32, 0xd7, 0x5d, 0x58, 0xd6, 0x43,
0x27, 0x66, 0x4c, 0xc6, 0x1f, 0xef, 0xc1, 0xac, 0xd0, 0x1f, 0xb7, 0x9d, 0xb5, 0x42, 0x89, 0xe8,
0x02, 0x51, 0xfb, 0x14, 0x2e, 0xa4, 0x48, 0x89, 0xe8, 0xe4, 0x2d, 0x68, 0x7a, 0xae, 0x65, 0x04,
0x1c, 0x6c, 0xd8, 0x96, 0x74, 0x06, 0x5e, 0x84, 0xbb, 0x6b, 0xd1, 0xe1, 0x7d, 0xe2, 0x7a, 0x59,
0x56, 0xce, 0x36, 0xbc, 0x0d, 0x2b, 0xe9, 0xe1, 0x7c, 0x7a, 0xed, 0x73, 0x58, 0xd5, 0xf1, 0xd8,
0x7d, 0x86, 0x5f, 0x97, 0x74, 0x07, 0xda, 0x59, 0x02, 0x31, 0xf1, 0x18, 0xda, 0x27, 0x26, 0x09,
0x83, 0xf3, 0x11, 0xbf, 0xa9, 0x12, 0x10, 0x47, 0x27, 0xa7, 0x83, 0x9a, 0x50, 0xb6, 0x3d, 0x31,
0xa8, 0x6c, 0x7b, 0xda, 0xe7, 0x50, 0x8b, 0x0e, 0x2d, 0xb4, 0x19, 0x47, 0x46, 0xe5, 0x57, 0x9c,
0x6c, 0x51, 0xcc, 0xf4, 0x38, 0xe3, 0xad, 0xc5, 0x4c, 0x9b, 0x00, 0x91, 0x9f, 0x91, 0x27, 0x25,
0xca, 0xd2, 0xd3, 0x15, 0x2c, 0xed, 0xef, 0x12, 0x4e, 0x47, 0x61, 0xd9, 0x8a, 0x58, 0xb6, 0x12,
0x4e, 0xa8, 0x7c, 0x1e, 0x27, 0x74, 0x07, 0x66, 0x02, 0x62, 0x12, 0xee, 0x06, 0x9b, 0xca, 0xe2,
0x92, 0x53, 0x62, 0x9d, 0xa3, 0xa1, 0xcb, 0x00, 0x03, 0x1f, 0x9b, 0x04, 0x5b, 0x86, 0xc9, 0xfd,
0x63, 0x45, 0xaf, 0x09, 0x48, 0x97, 0xa0, 0xfb, 0x30, 0x27, 0x23, 0x95, 0x19, 0xc6, 0xc6, 0x46,
0x0e, 0xc1, 0x84, 0xf4, 0x75, 0x39, 0x20, 0xde, 0xd3, 0xb3, 0x93, 0xf7, 0xb4, 0x18, 0xc7, 0x91,
0x15, 0xb7, 0x34, 0x57, 0xe8, 0x96, 0xf8, 0x88, 0xb3, 0xb8, 0xa5, 0x6a, 0xa1, 0x5b, 0x12, 0x34,
0x26, 0xba, 0xa5, 0xdf, 0xa5, 0x83, 0x79, 0x0a, 0xed, 0xec, 0x06, 0x11, 0x8e, 0xe1, 0x3d, 0x98,
0x0d, 0x18, 0x64, 0x82, 0x93, 0x11, 0x43, 0x04, 0xa2, 0xf6, 0x10, 0x96, 0x53, 0x16, 0xc0, 0x03,
0xc5, 0xc8, 0x5e, 0x4a, 0x67, 0xb2, 0x17, 0xed, 0xff, 0x4a, 0xaa, 0xf5, 0x3e, 0xb4, 0x47, 0x04,
0xfb, 0x19, 0xeb, 0x7d, 0x5f, 0x12, 0xe5, 0xa6, 0x7b, 0xb9, 0x88, 0x28, 0x8f, 0xe1, 0x84, 0x25,
0xf6, 0xa1, 0xc9, 0x74, 0x68, 0x04, 0x78, 0xc4, 0x0e, 0x44, 0x11, 0x8a, 0xfc, 0x30, 0x67, 0x34,
0x9f, 0x97, 0x1b, 0x40, 0x5f, 0xa0, 0x73, 0xf5, 0x35, 0x46, 0x2a, 0xac, 0xf3, 0x00, 0x50, 0x16,
0xe9, 0x5c, 0x7a, 0xf8, 0x92, 0xee, 0x7d, 0x9a, 0xb8, 0xe4, 0x78, 0xfa, 0x63, 0xc6, 0xc6, 0x04,
0x25, 0x70, 0x3e, 0x75, 0x81, 0xa8, 0xfd, 0x6d, 0x05, 0x20, 0xee, 0x7c, 0x63, 0x37, 0xfd, 0x87,
0xd1, 0x16, 0xe4, 0xd1, 0xc4, 0x95, 0x1c, 0x7a, 0xb9, 0x9b, 0xef, 0x61, 0x72, 0xf3, 0xf1, 0xb8,
0xe2, 0xad, 0xbc, 0xd1, 0x6f, 0xec, 0xb6, 0xdb, 0x82, 0x95, 0xb4, 0xba, 0xc5, 0xa6, 0xbb, 0x09,
0x33, 0x36, 0xc1, 0x63, 0x9e, 0x86, 0xab, 0xe9, 0x88, 0x82, 0xcb, 0x31, 0xb4, 0xab, 0x50, 0xdb,
0x1d, 0x9b, 0x43, 0xdc, 0xf7, 0xf0, 0x80, 0xce, 0x65, 0xd3, 0x86, 0x98, 0x9f, 0x37, 0xb4, 0x4d,
0xa8, 0x3e, 0xc6, 0xa7, 0x7c, 0x0f, 0x9e, 0x91, 0x3f, 0xed, 0x2f, 0xcb, 0xb0, 0xca, 0x7c, 0xe7,
0x96, 0x4c, 0x82, 0x75, 0x1c, 0xb8, 0xa1, 0x3f, 0xc0, 0x01, 0x53, 0xa9, 0x17, 0x1a, 0x1e, 0xf6,
0x6d, 0xd7, 0x12, 0x59, 0x5f, 0x6d, 0xe0, 0x85, 0xfb, 0x0c, 0x40, 0x13, 0x65, 0xda, 0xfd, 0x6d,
0xe8, 0x0a, 0xdb, 0xaa, 0xe8, 0xd5, 0x81, 0x17, 0xfe, 0x98, 0xb6, 0xe5, 0xd8, 0xe0, 0xc4, 0xf4,
0x71, 0xc0, 0x6c, 0x88, 0x8f, 0xed, 0x33, 0x00, 0x7a, 0x0f, 0x2e, 0x8c, 0xf1, 0xd8, 0xf5, 0x4f,
0x8d, 0x91, 0x3d, 0xb6, 0x89, 0x61, 0x3b, 0xc6, 0xd1, 0x29, 0xc1, 0x81, 0x30, 0x1c, 0xc4, 0x3b,
0x9f, 0xd0, 0xbe, 0x5d, 0xe7, 0x0b, 0xda, 0x83, 0x34, 0x68, 0xb8, 0xee, 0xd8, 0x08, 0x06, 0xae,
0x8f, 0x0d, 0xd3, 0xfa, 0x9a, 0x1d, 0x1e, 0x15, 0xbd, 0xee, 0xba, 0xe3, 0x3e, 0x85, 0x75, 0xad,
0xaf, 0xd1, 0x15, 0xa8, 0x0f, 0xbc, 0x30, 0xc0, 0xc4, 0xa0, 0x3f, 0xec, 0x90, 0xa8, 0xe9, 0xc0,
0x41, 0x5b, 0x5e, 0x18, 0x28, 0x08, 0x63, 0x2a, 0xf6, 0x39, 0x15, 0xe1, 0x29, 0x15, 0xb3, 0x09,
0x8d, 0x44, 0x1e, 0x49, 0xb3, 0x05, 0x96, 0x30, 0x8a, 0x6c, 0x81, 0x7e, 0x53, 0x98, 0xef, 0x8e,
0xa4, 0x24, 0xd9, 0x37, 0x85, 0x91, 0x53, 0x4f, 0xa6, 0x0a, 0xec, 0x9b, 0x8a, 0x7c, 0x84, 0x9f,
0x89, 0x3a, 0x40, 0x4d, 0xe7, 0x0d, 0xcd, 0x02, 0xd8, 0x32, 0x3d, 0xf3, 0xc8, 0x1e, 0xd9, 0xe4,
0x14, 0xdd, 0x84, 0x96, 0x69, 0x59, 0xc6, 0x40, 0x42, 0x6c, 0x2c, 0x8b, 0x32, 0x0b, 0xa6, 0x65,
0x6d, 0x29, 0x60, 0xf4, 0x03, 0x58, 0xb4, 0x7c, 0xd7, 0x4b, 0xe2, 0xf2, 0x2a, 0x4d, 0x8b, 0x76,
0xa8, 0xc8, 0xda, 0x3f, 0x4d, 0xc3, 0xe5, 0xa4, 0x62, 0xd3, 0x99, 0xf9, 0x87, 0x30, 0x9f, 0x9a,
0x35, 0x99, 0x12, 0xc7, 0x4c, 0xea, 0x09, 0xc4, 0x54, 0xee, 0x5a, 0xce, 0xe4, 0xae, 0xb9, 0x29,
0x7f, 0xe5, 0xfb, 0x48, 0xf9, 0xa7, 0xbf, 0x4b, 0xca, 0x3f, 0x73, 0xa6, 0x94, 0xff, 0x6d, 0x56,
0x81, 0x93, 0x83, 0x58, 0xe2, 0xc5, 0xcd, 0xa8, 0x11, 0xe1, 0x38, 0xb2, 0x52, 0x97, 0x2a, 0x0d,
0xcc, 0x9d, 0xa7, 0x34, 0x50, 0x2d, 0x2c, 0x0d, 0x50, 0x8b, 0xf0, 0x3c, 0xd3, 0x1f, 0xbb, 0xbe,
0xcc, 0xfd, 0xdb, 0x35, 0xc6, 0xc2, 0x82, 0x84, 0x8b, 0xbc, 0xbf, 0xb0, 0x4a, 0x00, 0x45, 0x55,
0x02, 0xb4, 0x01, 0xf3, 0x8e, 0x6b, 0x38, 0xf8, 0xb9, 0x41, 0x15, 0x16, 0xb4, 0xeb, 0x5c, 0x7b,
0x8e, 0xdb, 0xc3, 0xcf, 0xf7, 0x29, 0x44, 0xfb, 0xfb, 0x12, 0x2c, 0x27, 0x0d, 0x47, 0xe4, 0x85,
0x9f, 0x41, 0xcd, 0x97, 0xbe, 0x41, 0x18, 0xcb, 0x46, 0x32, 0xfe, 0xca, 0xfa, 0x10, 0x3d, 0x1e,
0x82, 0x7e, 0x5c, 0x58, 0x61, 0x78, 0xbb, 0x80, 0xcc, 0xab, 0x6a, 0x0c, 0x5a, 0x17, 0x16, 0x23,
0xe4, 0x89, 0xf9, 0xbd, 0x92, 0xaf, 0x97, 0x93, 0xf9, 0xba, 0x03, 0xb3, 0xdb, 0xf8, 0x99, 0x3d,
0xc0, 0xdf, 0x4b, 0x7d, 0x70, 0x03, 0xea, 0x1e, 0xf6, 0xc7, 0x76, 0x10, 0x44, 0x46, 0x5f, 0xd3,
0x55, 0x90, 0xf6, 0x9f, 0x33, 0xb0, 0x90, 0x96, 0xec, 0xbd, 0x4c, 0x79, 0xa0, 0x13, 0xef, 0xc2,
0xf4, 0xfa, 0x94, 0x33, 0xfa, 0x86, 0x3c, 0x06, 0xca, 0xa9, 0x2c, 0x21, 0x3a, 0x29, 0xc4, 0xd1,
0x40, 0xd7, 0x3f, 0x70, 0xc7, 0x63, 0xd3, 0xb1, 0x64, 0xed, 0x56, 0x34, 0xa9, 0xb4, 0x4c, 0x7f,
0x48, 0xb7, 0x16, 0x05, 0xb3, 0x6f, 0xea, 0x25, 0x69, 0xb4, 0x6d, 0x3b, 0xac, 0xba, 0xc0, 0x36,
0x4e, 0x4d, 0x07, 0x01, 0xda, 0xb6, 0x7d, 0x74, 0x1d, 0xa6, 0xb1, 0xf3, 0x4c, 0x9e, 0xc6, 0x71,
0x71, 0x57, 0x1e, 0x3f, 0x3a, 0xeb, 0x46, 0x6f, 0xc3, 0xec, 0xd8, 0x0d, 0x1d, 0x22, 0xe3, 0xee,
0x66, 0xb2, 0xc6, 0xa9, 0x8b, 0x5e, 0x74, 0x13, 0xe6, 0x2c, 0xa6, 0x03, 0x19, 0x5c, 0x2f, 0xc4,
0x15, 0x0a, 0x06, 0xd7, 0x65, 0x3f, 0xfa, 0x24, 0x8a, 0x23, 0x6a, 0xa9, 0x48, 0x20, 0x25, 0xd4,
0xdc, 0x60, 0xe2, 0x71, 0x32, 0x98, 0x00, 0x46, 0xe2, 0x66, 0x21, 0x89, 0xc9, 0xf5, 0x85, 0x35,
0xa8, 0x8e, 0xdc, 0x21, 0xb7, 0x83, 0x3a, 0xaf, 0xf4, 0x8f, 0xdc, 0x21, 0x33, 0x83, 0x65, 0x1a,
0x3c, 0x59, 0xb6, 0xd3, 0x9e, 0x67, 0xdb, 0x8b, 0x37, 0xe8, 0x99, 0xc8, 0x3e, 0x0c, 0xd7, 0x19,
0xe0, 0x76, 0x83, 0x75, 0xd5, 0x18, 0x64, 0xcf, 0x19, 0xb0, 0x23, 0x9b, 0x90, 0xd3, 0x76, 0x93,
0xc1, 0xe9, 0x27, 0x8d, 0x79, 0x79, 0xb6, 0xb3, 0x90, 0x8a, 0x79, 0xf3, 0xf6, 0xe7, 0x1b, 0x50,
0xc0, 0xf8, 0xc7, 0x12, 0xac, 0x6c, 0xb1, 0x90, 0x4f, 0xf1, 0x04, 0xe7, 0x48, 0xc0, 0xd1, 0xdd,
0xa8, 0xd2, 0x91, 0xce, 0xa3, 0xd3, 0x8b, 0x15, 0x78, 0xe8, 0x01, 0x34, 0x25, 0x4d, 0x31, 0xb2,
0xf2, 0xaa, 0x1a, 0x49, 0x23, 0x50, 0x9b, 0xda, 0x27, 0xb0, 0x9a, 0xe1, 0x59, 0x84, 0x67, 0x57,
0x61, 0x3e, 0xf6, 0x08, 0x11, 0xcb, 0xf5, 0x08, 0xb6, 0x6b, 0x69, 0xf7, 0xe1, 0x42, 0x9f, 0x98,
0x3e, 0xc9, 0x2c, 0xf8, 0x0c, 0x63, 0x59, 0x99, 0x24, 0x39, 0x56, 0x54, 0x32, 0xfa, 0xb0, 0xdc,
0x27, 0xae, 0xf7, 0x1a, 0x44, 0xe9, 0x4e, 0xa7, 0xcb, 0x76, 0x43, 0x22, 0x62, 0x32, 0xd9, 0xd4,
0x56, 0x79, 0x51, 0x27, 0x3b, 0xdb, 0xc7, 0xb0, 0xc2, 0x6b, 0x2a, 0xaf, 0xb3, 0x88, 0x35, 0x59,
0xd1, 0xc9, 0xd2, 0xdd, 0x86, 0xa5, 0xd8, 0x95, 0xc7, 0xe9, 0xe1, 0xed, 0x64, 0x7a, 0xb8, 0x9a,
0xd5, 0x71, 0x22, 0x3b, 0xfc, 0xab, 0xb2, 0xe2, 0x30, 0x0b, 0x92, 0xc3, 0xcd, 0x64, 0x72, 0x78,
0xa9, 0x80, 0x64, 0x22, 0x37, 0xcc, 0x5a, 0x64, 0x25, 0xc7, 0x22, 0xf5, 0x4c, 0x06, 0x39, 0x9d,
0x2a, 0x66, 0xa7, 0x78, 0xfb, 0xad, 0x24, 0x90, 0xbb, 0x3c, 0x81, 0x8c, 0xa6, 0x8e, 0xea, 0x5c,
0x77, 0x53, 0x09, 0x64, 0xbb, 0x88, 0xcd, 0x28, 0x7f, 0xfc, 0xf3, 0x69, 0xa8, 0x45, 0x7d, 0x19,
0xc1, 0x66, 0x85, 0x54, 0xce, 0x11, 0x92, 0x7a, 0x7e, 0x55, 0x5e, 0xe7, 0xfc, 0x9a, 0x7e, 0xd5,
0xf9, 0x75, 0x11, 0x6a, 0xec, 0xc3, 0xf0, 0xf1, 0xb1, 0x38, 0x8f, 0xaa, 0x0c, 0xa0, 0xe3, 0xe3,
0xd8, 0xa0, 0x66, 0xcf, 0x62, 0x50, 0xa9, 0x4c, 0x75, 0x2e, 0x9d, 0xa9, 0xde, 0x8b, 0x4e, 0x18,
0x7e, 0x16, 0xad, 0x67, 0xc9, 0xe5, 0x9e, 0x2d, 0x3b, 0xc9, 0xb3, 0x85, 0x1f, 0x4f, 0xd7, 0x72,
0x06, 0xbf, 0xb1, 0x79, 0xea, 0x13, 0x9e, 0xa7, 0xaa, 0x56, 0x25, 0x1c, 0xe1, 0x26, 0x40, 0xb4,
0xe7, 0x65, 0xb2, 0x8a, 0xb2, 0x4b, 0xd3, 0x15, 0x2c, 0xea, 0x55, 0x12, 0xf2, 0x8f, 0x8b, 0xb1,
0x67, 0xf0, 0x2a, 0xff, 0xa2, 0x46, 0x49, 0x05, 0xf5, 0xcc, 0x7b, 0x99, 0xd2, 0xc6, 0xd9, 0xac,
0xee, 0x76, 0xb2, 0xb2, 0x71, 0x3e, 0x73, 0xc9, 0x14, 0x36, 0xd8, 0xa1, 0x6e, 0xfa, 0xa2, 0x9b,
0xe7, 0xa4, 0x35, 0x01, 0xe9, 0x12, 0x1a, 0x4a, 0x1d, 0xdb, 0x8e, 0x1d, 0x9c, 0xf0, 0xfe, 0x59,
0xd6, 0x0f, 0x12, 0xd4, 0x65, 0xb7, 0xda, 0xf8, 0x85, 0x4d, 0x8c, 0x81, 0x6b, 0x61, 0x66, 0x8c,
0x33, 0x7a, 0x95, 0x02, 0xb6, 0x5c, 0x0b, 0xc7, 0x1b, 0xa4, 0x7a, 0xae, 0x0d, 0x52, 0x4b, 0x6d,
0x90, 0x15, 0x98, 0xf5, 0xb1, 0x19, 0xb8, 0x8e, 0x48, 0x0c, 0x44, 0x8b, 0x9e, 0x15, 0x63, 0x1c,
0x04, 0x74, 0x02, 0x11, 0xc0, 0x88, 0xa6, 0x12, 0x66, 0xcd, 0x17, 0x85, 0x59, 0x13, 0x0a, 0xa6,
0xa9, 0x30, 0xab, 0x51, 0x14, 0x66, 0x9d, 0xa5, 0x5e, 0xaa, 0x04, 0x91, 0xcd, 0x89, 0x41, 0xa4,
0x1a, 0x8e, 0x2d, 0x24, 0xc2, 0xb1, 0xdf, 0xe5, 0x9e, 0x7a, 0x0c, 0xab, 0x99, 0x5d, 0x20, 0x36,
0xd5, 0xdd, 0x54, 0xc5, 0xb5, 0x5d, 0x24, 0xa0, 0xa8, 0xe0, 0xfa, 0xc7, 0x70, 0xe5, 0xd0, 0xb3,
0x52, 0xa1, 0x8a, 0x48, 0xb4, 0xce, 0x1e, 0x21, 0xdc, 0x93, 0x51, 0x65, 0xf9, 0x8c, 0x39, 0x1c,
0x47, 0xd7, 0x34, 0xd8, 0x28, 0x9e, 0x5d, 0x1c, 0xf9, 0x7f, 0x08, 0x0b, 0x3b, 0x2f, 0xf0, 0xa0,
0x7f, 0xea, 0x0c, 0xce, 0xc1, 0x51, 0x0b, 0x2a, 0x83, 0xb1, 0x25, 0x4a, 0x19, 0xf4, 0x53, 0x8d,
0x62, 0x2a, 0xc9, 0x28, 0xc6, 0x80, 0x56, 0x3c, 0x83, 0x90, 0xe4, 0x0a, 0x95, 0xa4, 0x45, 0x91,
0x29, 0xf1, 0x79, 0x5d, 0xb4, 0x04, 0x1c, 0xfb, 0x3e, 0x5b, 0x2a, 0x87, 0x63, 0xdf, 0x4f, 0xee,
0xb9, 0x4a, 0x72, 0xcf, 0x69, 0x7f, 0x53, 0x82, 0x3a, 0x9d, 0xe1, 0x3b, 0xf1, 0x2f, 0x62, 0xf9,
0x4a, 0x1c, 0xcb, 0x47, 0x29, 0xc1, 0xb4, 0x9a, 0x12, 0xc4, 0x9c, 0xcf, 0x30, 0x70, 0x96, 0xf3,
0xd9, 0x08, 0x8e, 0x7d, 0x5f, 0xdb, 0x80, 0x79, 0xce, 0x9b, 0x58, 0x79, 0x0b, 0x2a, 0xa1, 0x3f,
0x92, 0xa6, 0x18, 0xfa, 0x23, 0xed, 0x2f, 0x4a, 0xd0, 0xe8, 0x12, 0x62, 0x0e, 0x4e, 0xce, 0xb1,
0x80, 0x88, 0xb9, 0xb2, 0xca, 0x5c, 0x76, 0x11, 0x31, 0xbb, 0xd3, 0x05, 0xec, 0xce, 0x24, 0xd8,
0xd5, 0xa0, 0x29, 0x79, 0x29, 0x64, 0xb8, 0x07, 0x68, 0xdf, 0xf5, 0xc9, 0x43, 0xd7, 0x7f, 0x6e,
0xfa, 0xd6, 0xf9, 0xf2, 0x05, 0x04, 0xd3, 0xe2, 0xbd, 0x50, 0xe5, 0xc6, 0x8c, 0xce, 0xbe, 0xb5,
0x77, 0x60, 0x29, 0x41, 0xaf, 0x70, 0xe2, 0x0f, 0xa1, 0xce, 0xdc, 0xa8, 0x88, 0x29, 0x6f, 0xa8,
0x35, 0xd5, 0x49, 0xbe, 0x56, 0xeb, 0xc2, 0x22, 0x3d, 0x27, 0x19, 0x3c, 0xda, 0x78, 0x3f, 0x4c,
0x45, 0x5e, 0xcb, 0xc9, 0xf1, 0xa9, 0xa8, 0xeb, 0x1f, 0x4a, 0x30, 0xc3, 0xe0, 0x99, 0x53, 0xed,
0x22, 0xd4, 0x7c, 0xec, 0xb9, 0x06, 0x31, 0x87, 0xd1, 0x13, 0x2c, 0x0a, 0x38, 0x30, 0x87, 0x01,
0x7b, 0x41, 0x46, 0x3b, 0x2d, 0x7b, 0x88, 0x03, 0x22, 0xdf, 0x61, 0xd5, 0x29, 0x6c, 0x9b, 0x83,
0xa8, 0x48, 0x02, 0xfb, 0x8f, 0x78, 0x48, 0x35, 0xad, 0xb3, 0x6f, 0x74, 0x9d, 0xbf, 0x6e, 0x98,
0x50, 0x00, 0x63, 0x4f, 0x1e, 0x3a, 0x50, 0x4d, 0xd5, 0xbc, 0xa2, 0xb6, 0xf6, 0x09, 0x20, 0x75,
0xcd, 0x42, 0xa8, 0x6f, 0xc3, 0x2c, 0x13, 0x89, 0x8c, 0x09, 0x9a, 0xc9, 0x45, 0xeb, 0xa2, 0x57,
0xfb, 0x0c, 0x10, 0x97, 0x62, 0x22, 0x0e, 0x38, 0xbb, 0xc4, 0x3f, 0x86, 0xa5, 0xc4, 0xf8, 0xe8,
0x32, 0x3b, 0x41, 0x20, 0x3d, 0xbb, 0x18, 0xfc, 0xeb, 0x12, 0x40, 0x37, 0x24, 0x27, 0xa2, 0xd8,
0xa2, 0xae, 0xb2, 0x94, 0x5c, 0x25, 0xed, 0xf3, 0xcc, 0x20, 0x78, 0xee, 0xfa, 0x32, 0xd0, 0x8d,
0xda, 0xac, 0x50, 0x12, 0x92, 0x13, 0x59, 0xe0, 0xa5, 0xdf, 0xe8, 0x3a, 0x34, 0xf9, 0xcb, 0x39,
0xc3, 0xb4, 0x2c, 0x1f, 0x07, 0x81, 0xa8, 0xf4, 0x36, 0x38, 0xb4, 0xcb, 0x81, 0x14, 0xcd, 0xb6,
0xb0, 0x43, 0x6c, 0x72, 0x6a, 0x10, 0xf7, 0x1b, 0xec, 0x88, 0x10, 0xb6, 0x21, 0xa1, 0x07, 0x14,
0x48, 0xd1, 0x7c, 0x3c, 0xb4, 0x03, 0xe2, 0x4b, 0x34, 0x59, 0x79, 0x14, 0x50, 0x86, 0xa6, 0xfd,
0xb2, 0x04, 0xad, 0xfd, 0x70, 0x34, 0xe2, 0x8b, 0x3c, 0xaf, 0x2c, 0xd1, 0x3b, 0x62, 0x1d, 0xe5,
0x94, 0x35, 0xc4, 0x22, 0x12, 0x8b, 0xfb, 0xee, 0xa9, 0xf5, 0x5d, 0x58, 0x54, 0x18, 0x15, 0x4a,
0x4b, 0x44, 0x2a, 0xa5, 0x64, 0xa4, 0x42, 0x0d, 0x85, 0x67, 0x93, 0xaf, 0xb7, 0x38, 0xed, 0x02,
0x2c, 0x25, 0xc6, 0x8b, 0x63, 0xe9, 0x16, 0x34, 0xc4, 0x85, 0xb2, 0x30, 0x82, 0x35, 0xa8, 0x52,
0xf7, 0x32, 0xb0, 0x2d, 0x59, 0xd9, 0x9f, 0xf3, 0x5c, 0x6b, 0xcb, 0xb6, 0x7c, 0xad, 0x07, 0x0d,
0x9d, 0x93, 0x17, 0xb8, 0x9f, 0x42, 0x53, 0x5c, 0x3f, 0x1b, 0x89, 0x67, 0x18, 0x71, 0x19, 0x3a,
0x41, 0x5b, 0x6f, 0x38, 0x6a, 0x53, 0xfb, 0x39, 0x74, 0xf8, 0xb1, 0x99, 0xa0, 0x2a, 0x97, 0xf6,
0x29, 0xc8, 0x97, 0x9d, 0x45, 0xc4, 0x93, 0xc3, 0x1a, 0xbe, 0xda, 0xd4, 0x2e, 0xc3, 0xc5, 0x5c,
0xe2, 0x62, 0xdd, 0x1e, 0xb4, 0xe2, 0x0e, 0xcb, 0x96, 0x17, 0x1a, 0xec, 0xa2, 0xa2, 0xa4, 0x5c,
0x54, 0xac, 0x44, 0xa1, 0x48, 0x59, 0xfa, 0x6f, 0x16, 0x72, 0xc7, 0x81, 0x63, 0xa5, 0x28, 0x70,
0x9c, 0x4e, 0x04, 0x8e, 0xda, 0x97, 0x91, 0xf4, 0x44, 0xd4, 0xfe, 0x11, 0x4b, 0x1d, 0xf8, 0xdc,
0xd2, 0x4d, 0xac, 0xe5, 0x2c, 0x8e, 0x63, 0xe8, 0x0a, 0xb2, 0xb6, 0x00, 0x8d, 0x84, 0xc3, 0xd0,
0x1e, 0x40, 0x33, 0xe5, 0x01, 0xee, 0xa4, 0x62, 0xa8, 0x8c, 0xd8, 0x52, 0x11, 0xd4, 0xb2, 0x70,
0x44, 0x0f, 0x83, 0x5d, 0xe7, 0xd8, 0x95, 0x74, 0xaf, 0x41, 0xfd, 0xb0, 0xe8, 0xa1, 0xe3, 0xb4,
0xbc, 0x29, 0x7b, 0x07, 0x16, 0xfb, 0xc4, 0xf5, 0xcd, 0x21, 0xde, 0x65, 0xbb, 0xf6, 0xd8, 0xe6,
0x37, 0x41, 0x61, 0x18, 0xf9, 0x6f, 0xf6, 0xad, 0xfd, 0x7b, 0x09, 0x16, 0x1e, 0xda, 0x23, 0x1c,
0x9c, 0x06, 0x04, 0x8f, 0x0f, 0x59, 0x3c, 0x7d, 0x09, 0x6a, 0x94, 0x9b, 0x80, 0x98, 0x63, 0x4f,
0xde, 0xa4, 0x45, 0x00, 0x2a, 0xa3, 0x80, 0x93, 0x96, 0x19, 0xb6, 0x9a, 0xcb, 0x64, 0x66, 0xa5,
0xf9, 0x85, 0x00, 0xa1, 0xf7, 0x01, 0xc2, 0x00, 0x5b, 0xe2, 0xf6, 0xac, 0x92, 0x3a, 0x7a, 0x0e,
0xd5, 0x3b, 0x0e, 0x8a, 0xc7, 0xaf, 0xd2, 0x3e, 0x80, 0xba, 0xed, 0xb8, 0x16, 0x66, 0x77, 0x1c,
0x96, 0xc8, 0xbe, 0xf3, 0x47, 0x01, 0x47, 0x3c, 0x0c, 0xb0, 0xa5, 0xfd, 0x81, 0xf0, 0xc2, 0x52,
0x78, 0x42, 0x07, 0x3b, 0xb0, 0xc8, 0x37, 0xf4, 0x71, 0xb4, 0x68, 0xa9, 0xe8, 0x38, 0xa4, 0x4d,
0x09, 0x44, 0x6f, 0xd9, 0xe2, 0x54, 0x94, 0x23, 0xb4, 0xfb, 0x70, 0x21, 0x11, 0xf7, 0x9e, 0x27,
0x5d, 0x7c, 0x94, 0xca, 0x35, 0x63, 0x03, 0x11, 0xc9, 0x9e, 0xb4, 0x8f, 0x82, 0x64, 0x2f, 0xe0,
0xc9, 0x5e, 0xa0, 0xe9, 0xb0, 0x96, 0x48, 0x81, 0x13, 0x8c, 0x7c, 0x90, 0x3a, 0xe2, 0x2f, 0x17,
0x10, 0x4b, 0x9d, 0xf5, 0xff, 0x53, 0x82, 0xe5, 0x3c, 0x84, 0xd7, 0x2c, 0xb6, 0xfc, 0xa4, 0xe0,
0x4d, 0xc3, 0xdd, 0x89, 0xdc, 0xfc, 0x56, 0xca, 0x52, 0x8f, 0xa1, 0x93, 0x27, 0xbd, 0xac, 0x2a,
0x2a, 0x67, 0x50, 0xc5, 0xff, 0x96, 0x95, 0xf2, 0x61, 0x97, 0x10, 0xdf, 0x3e, 0x0a, 0xa9, 0xf1,
0x7e, 0x5f, 0x65, 0x80, 0x07, 0x51, 0x8a, 0xcb, 0xe5, 0x77, 0x23, 0x3b, 0x2a, 0x9e, 0x35, 0x37,
0xcd, 0xdd, 0x4b, 0xa6, 0xb9, 0xbc, 0x30, 0x78, 0x7b, 0x22, 0x99, 0x37, 0xb6, 0xf6, 0xf3, 0xb2,
0x04, 0xcd, 0xa4, 0x1e, 0xd0, 0x27, 0x00, 0x66, 0xc4, 0xb9, 0x30, 0xf9, 0x4b, 0x93, 0x56, 0xa7,
0x2b, 0xf8, 0xe8, 0x1a, 0x54, 0x06, 0x5e, 0x28, 0x34, 0x12, 0xdf, 0x10, 0x6d, 0x79, 0x21, 0x77,
0x00, 0xb4, 0x97, 0x06, 0xcd, 0xfc, 0xa6, 0x3f, 0xe3, 0xb9, 0x9e, 0x32, 0x30, 0x47, 0x15, 0x38,
0xe8, 0x73, 0x68, 0x3e, 0xf7, 0x6d, 0x62, 0x1e, 0x8d, 0xb0, 0x31, 0x32, 0x4f, 0xb1, 0x2f, 0x3c,
0x57, 0xb1, 0x97, 0x69, 0x48, 0xfc, 0x27, 0x14, 0x5d, 0x0b, 0xa1, 0x2a, 0xe7, 0x7f, 0x85, 0x47,
0x7e, 0x0c, 0xab, 0x21, 0x45, 0x33, 0xd8, 0x6b, 0x03, 0xc7, 0x74, 0x5c, 0x23, 0xc0, 0xf4, 0x68,
0x92, 0x2f, 0xfc, 0xf2, 0xbd, 0xe5, 0x32, 0x1b, 0xb4, 0xe5, 0xfa, 0xb8, 0x67, 0x3a, 0x6e, 0x9f,
0x8f, 0xd0, 0xc6, 0x50, 0x57, 0x96, 0xf3, 0x8a, 0x99, 0x1f, 0xc0, 0xa2, 0xbc, 0x7b, 0x0b, 0x30,
0x11, 0x7e, 0x7d, 0xd2, 0x9c, 0x0b, 0x02, 0xbd, 0x8f, 0x09, 0xf3, 0xee, 0xb7, 0x2e, 0x41, 0x55,
0xfe, 0xc9, 0x02, 0xcd, 0x41, 0xe5, 0x60, 0x6b, 0xbf, 0x35, 0x45, 0x3f, 0x0e, 0xb7, 0xf7, 0x5b,
0xa5, 0x5b, 0x63, 0x68, 0xa5, 0xff, 0x60, 0x80, 0x56, 0x61, 0x69, 0x5f, 0xdf, 0xdb, 0xef, 0x3e,
0xea, 0x1e, 0xec, 0xee, 0xf5, 0x8c, 0x7d, 0x7d, 0xf7, 0xab, 0xee, 0xc1, 0x4e, 0x6b, 0x0a, 0x5d,
0x85, 0xcb, 0x6a, 0xc7, 0xef, 0xef, 0xf5, 0x0f, 0x8c, 0x83, 0x3d, 0x63, 0x6b, 0xaf, 0x77, 0xd0,
0xdd, 0xed, 0xed, 0xe8, 0xad, 0x12, 0xba, 0x0c, 0x6b, 0x2a, 0xca, 0x17, 0xbb, 0xdb, 0xbb, 0xfa,
0xce, 0x16, 0xfd, 0xee, 0x3e, 0x69, 0x95, 0x6f, 0xdd, 0x87, 0x85, 0xd4, 0x83, 0x21, 0xb4, 0x08,
0x8d, 0x7e, 0xb7, 0xb7, 0xfd, 0xc5, 0xde, 0x4f, 0x0d, 0x7d, 0xa7, 0xbb, 0xfd, 0xb3, 0xd6, 0x14,
0x5a, 0x86, 0x96, 0x04, 0xf5, 0xf6, 0x0e, 0x38, 0xb4, 0x74, 0xeb, 0x9b, 0x94, 0x49, 0x62, 0x74,
0x01, 0x16, 0xa3, 0xb9, 0x8d, 0x2d, 0x7d, 0xa7, 0x7b, 0xb0, 0xb3, 0xdd, 0x9a, 0x4a, 0x82, 0xf5,
0xc3, 0x5e, 0x6f, 0xb7, 0xf7, 0xa8, 0x55, 0xa2, 0x54, 0x63, 0xf0, 0xce, 0x4f, 0x77, 0x29, 0x72,
0x39, 0x89, 0x7c, 0xd8, 0x7b, 0xdc, 0xdb, 0xfb, 0x49, 0xaf, 0x55, 0xd9, 0xfc, 0xb7, 0x06, 0x34,
0x65, 0xcc, 0x80, 0x7d, 0x76, 0x21, 0xfc, 0x19, 0xcc, 0xc9, 0xbf, 0xdb, 0xc4, 0xce, 0x2a, 0xf9,
0xdf, 0xa0, 0x4e, 0x3b, 0xdb, 0x21, 0x62, 0xaf, 0x29, 0xb4, 0xcf, 0x62, 0x21, 0xe5, 0x71, 0xd6,
0x65, 0x35, 0x3a, 0xc9, 0xbc, 0xfe, 0xea, 0xac, 0x17, 0x75, 0x47, 0x14, 0xfb, 0x34, 0x00, 0x52,
0x1f, 0xd6, 0xa2, 0x75, 0x35, 0x4c, 0xc8, 0x3e, 0xd8, 0xed, 0x5c, 0x29, 0xec, 0x8f, 0x88, 0xfe,
0x0c, 0x5a, 0xe9, 0x27, 0xb5, 0x28, 0x2e, 0x0a, 0x15, 0x3c, 0xd7, 0xed, 0x5c, 0x9d, 0x80, 0xa1,
0x92, 0xce, 0x3c, 0x4b, 0xdd, 0x28, 0x7e, 0x58, 0x98, 0x21, 0x5d, 0xf4, 0x5a, 0x91, 0x8b, 0x22,
0xf9, 0xa8, 0x0a, 0xa9, 0x8f, 0x41, 0x73, 0x1e, 0xd7, 0x29, 0xa2, 0xc8, 0x7f, 0x8d, 0xa5, 0x4d,
0xa1, 0xaf, 0x60, 0x21, 0x75, 0x17, 0x88, 0xe2, 0x51, 0xf9, 0x37, 0x9b, 0x9d, 0x8d, 0x62, 0x84,
0xa4, 0xde, 0xd4, 0x9b, 0xbe, 0x84, 0xde, 0x72, 0xae, 0x0f, 0x13, 0x7a, 0xcb, 0xbd, 0x22, 0x64,
0xe6, 0x95, 0xb8, 0xcf, 0x53, 0xcc, 0x2b, 0xef, 0xf2, 0xb0, 0xb3, 0x5e, 0xd4, 0xad, 0x2e, 0x3f,
0x75, 0x97, 0xa7, 0x2c, 0x3f, 0xff, 0x8a, 0xb0, 0xb3, 0x51, 0x8c, 0x90, 0xd6, 0x55, 0x7c, 0xb1,
0x90, 0xd2, 0x55, 0xe6, 0x1e, 0x2b, 0xa5, 0xab, 0xec, 0x8d, 0x84, 0xd0, 0x55, 0xea, 0x86, 0xe0,
0x4a, 0x61, 0x05, 0x35, 0xab, 0xab, 0xfc, 0xa2, 0xac, 0x36, 0x85, 0xbe, 0x85, 0x76, 0x51, 0x99,
0x13, 0xc5, 0x31, 0xc2, 0x2b, 0xea, 0xb0, 0x9d, 0x9b, 0x67, 0xc0, 0x8c, 0xa6, 0xec, 0x42, 0x55,
0xd6, 0x34, 0x51, 0xec, 0x50, 0x52, 0x85, 0xd4, 0xce, 0x5a, 0x4e, 0x4f, 0x44, 0xe2, 0x03, 0x98,
0xa6, 0x50, 0xb4, 0x9c, 0x40, 0x92, 0x43, 0x2f, 0xa4, 0xa0, 0xd1, 0xb0, 0x8f, 0x61, 0x96, 0x17,
0xe8, 0x50, 0x9c, 0x39, 0x25, 0xaa, 0x87, 0x9d, 0xd5, 0x0c, 0x3c, 0x1a, 0xfc, 0x25, 0xff, 0xd7,
0x9f, 0xa8, 0xb4, 0xa1, 0x8b, 0x89, 0x3f, 0x88, 0x24, 0xeb, 0x79, 0x9d, 0x4b, 0xf9, 0x9d, 0xaa,
0x89, 0xa4, 0xc2, 0x8f, 0xf5, 0xa2, 0xf8, 0x30, 0x63, 0x22, 0xf9, 0xf1, 0xa6, 0x36, 0x85, 0x0c,
0x5e, 0xb4, 0x4a, 0x11, 0xd6, 0xf2, 0x6d, 0x2b, 0x41, 0xfc, 0xda, 0x44, 0x9c, 0x68, 0x82, 0x23,
0x58, 0xca, 0x49, 0xbf, 0xd1, 0xb5, 0x94, 0xf2, 0xf3, 0x32, 0xff, 0xce, 0x5b, 0x93, 0x91, 0x54,
0x15, 0x09, 0xf3, 0x5e, 0x51, 0x7d, 0x82, 0x62, 0xd5, 0xab, 0x19, 0xb8, 0x1c, 0xbc, 0xf9, 0xa7,
0x15, 0x98, 0xe7, 0x45, 0x12, 0x71, 0xa6, 0x3d, 0x02, 0x88, 0xeb, 0x78, 0xa8, 0x93, 0x58, 0x66,
0xa2, 0xa0, 0xd9, 0xb9, 0x98, 0xdb, 0xa7, 0x2a, 0x5f, 0x29, 0xc9, 0x29, 0xca, 0xcf, 0x16, 0xfa,
0x14, 0xe5, 0xe7, 0x54, 0xf1, 0xb4, 0x29, 0xb4, 0x0d, 0xb5, 0xa8, 0x4e, 0x84, 0x94, 0xf2, 0x52,
0xaa, 0xc8, 0xd5, 0xe9, 0xe4, 0x75, 0xa9, 0x1c, 0x29, 0xb5, 0x1f, 0x85, 0xa3, 0x6c, 0x45, 0x49,
0xe1, 0x28, 0xaf, 0x5c, 0x14, 0xaf, 0x8e, 0xa7, 0xba, 0xe9, 0xd5, 0x25, 0xaa, 0x07, 0xe9, 0xd5,
0x25, 0xb3, 0x63, 0x6d, 0xea, 0x8b, 0x4b, 0xbf, 0xfa, 0xcd, 0x7a, 0xe9, 0x3f, 0x7e, 0xb3, 0x3e,
0xf5, 0x27, 0x2f, 0xd7, 0x4b, 0xbf, 0x7a, 0xb9, 0x5e, 0xfa, 0xd7, 0x97, 0xeb, 0xa5, 0xff, 0x7a,
0xb9, 0x5e, 0xfa, 0xc5, 0x7f, 0xaf, 0x4f, 0x1d, 0xcd, 0xb2, 0xbf, 0xc1, 0xbe, 0xff, 0xff, 0x01,
0x00, 0x00, 0xff, 0xff, 0x61, 0x12, 0x07, 0xa4, 0xba, 0x3c, 0x00, 0x00,
0x94, 0xb6, 0x29, 0xcd, 0xee, 0x66, 0x03, 0x74, 0x5a, 0xec, 0x12, 0xd5, 0x33, 0x64, 0x77, 0x4f,
0x77, 0xb5, 0x6d, 0x05, 0x39, 0x24, 0x97, 0x20, 0x97, 0x00, 0x9b, 0x63, 0x6e, 0x39, 0x04, 0x58,
0xe4, 0x92, 0x43, 0x0e, 0x41, 0x7e, 0x41, 0xb0, 0x97, 0x05, 0x02, 0x04, 0x08, 0x92, 0x5b, 0xd6,
0x39, 0xe4, 0x10, 0x20, 0xbf, 0x61, 0x51, 0x5f, 0xdd, 0xd5, 0x5f, 0xb4, 0xe4, 0x19, 0xec, 0xfa,
0xc4, 0xae, 0x57, 0xaf, 0x5e, 0xbd, 0x7a, 0xef, 0xd5, 0xab, 0xf7, 0x5e, 0x15, 0xa1, 0x66, 0x7a,
0xf6, 0x1d, 0xcf, 0x77, 0x89, 0x8b, 0xe6, 0xfc, 0xd0, 0x21, 0xf6, 0x18, 0x77, 0x6e, 0x0f, 0x6d,
0x72, 0x12, 0x1e, 0xdd, 0x19, 0xb8, 0xe3, 0x77, 0x87, 0xee, 0xd0, 0x7d, 0x97, 0xf5, 0x1f, 0x85,
0xc7, 0xac, 0xc5, 0x1a, 0xec, 0x8b, 0x8f, 0xd3, 0x6e, 0x41, 0xf3, 0x2b, 0xec, 0x07, 0xb6, 0xeb,
0xe8, 0xf8, 0xdb, 0x10, 0x07, 0x04, 0xb5, 0x61, 0xee, 0x19, 0x87, 0xb4, 0x4b, 0x1b, 0xa5, 0x1b,
0x35, 0x5d, 0x36, 0xb5, 0x5f, 0x96, 0x60, 0x21, 0x42, 0x0e, 0x3c, 0xd7, 0x09, 0x70, 0x31, 0x36,
0xba, 0x0a, 0xf3, 0x82, 0x27, 0xc3, 0x31, 0xc7, 0xb8, 0x5d, 0x66, 0xdd, 0x75, 0x01, 0xeb, 0x99,
0x63, 0x8c, 0xde, 0x81, 0x05, 0x89, 0x22, 0x89, 0x54, 0x18, 0x56, 0x53, 0x80, 0xc5, 0x6c, 0xe8,
0x0e, 0x2c, 0x49, 0x44, 0xd3, 0xb3, 0x23, 0xe4, 0x69, 0x86, 0xbc, 0x28, 0xba, 0xba, 0x9e, 0x2d,
0xf0, 0xb5, 0x9f, 0x43, 0x6d, 0xbb, 0xd7, 0xdf, 0x72, 0x9d, 0x63, 0x7b, 0x48, 0x59, 0x0c, 0xb0,
0x4f, 0xc7, 0xb4, 0x4b, 0x1b, 0x15, 0xca, 0xa2, 0x68, 0xa2, 0x0e, 0x54, 0x03, 0x6c, 0xfa, 0x83,
0x13, 0x1c, 0xb4, 0xcb, 0xac, 0x2b, 0x6a, 0xd3, 0x51, 0xae, 0x47, 0x6c, 0xd7, 0x09, 0xda, 0x15,
0x3e, 0x4a, 0x34, 0xb5, 0xbf, 0x2d, 0x41, 0x7d, 0xdf, 0xf5, 0xc9, 0x53, 0xd3, 0xf3, 0x6c, 0x67,
0x88, 0x6e, 0x43, 0x95, 0xc9, 0x72, 0xe0, 0x8e, 0x98, 0x0c, 0x9a, 0x9b, 0x8b, 0x77, 0x04, 0x4b,
0x77, 0xf6, 0x45, 0x87, 0x1e, 0xa1, 0xa0, 0xeb, 0xd0, 0x1c, 0xb8, 0x0e, 0x31, 0x6d, 0x07, 0xfb,
0x86, 0xe7, 0xfa, 0x84, 0x49, 0x66, 0x46, 0x6f, 0x44, 0x50, 0x4a, 0x1c, 0x5d, 0x84, 0xda, 0x89,
0x1b, 0x10, 0x8e, 0x51, 0x61, 0x18, 0x55, 0x0a, 0x60, 0x9d, 0xab, 0x30, 0xc7, 0x3a, 0x6d, 0x4f,
0xc8, 0x60, 0x96, 0x36, 0x77, 0x3d, 0xed, 0xd7, 0x25, 0x98, 0x79, 0xea, 0x86, 0x0e, 0x49, 0x4d,
0x63, 0x92, 0x13, 0xa1, 0x1f, 0x65, 0x1a, 0x93, 0x9c, 0xc4, 0xd3, 0x50, 0x0c, 0xae, 0x22, 0x3e,
0x0d, 0xed, 0xec, 0x40, 0xd5, 0xc7, 0xa6, 0xe5, 0x3a, 0xa3, 0x53, 0xc6, 0x42, 0x55, 0x8f, 0xda,
0x54, 0x77, 0x01, 0x1e, 0xd9, 0x4e, 0xf8, 0xc2, 0xf0, 0xf1, 0xc8, 0x3c, 0xc2, 0x23, 0xc6, 0x4a,
0x55, 0x6f, 0x0a, 0xb0, 0xce, 0xa1, 0xe8, 0x63, 0xa8, 0x7b, 0xbe, 0xeb, 0x99, 0x43, 0x93, 0x8a,
0xaf, 0x3d, 0xc3, 0x24, 0xb4, 0x16, 0x49, 0x88, 0x71, 0xbb, 0x1f, 0x23, 0xe8, 0x2a, 0xb6, 0xf6,
0x35, 0x2c, 0x50, 0x4b, 0x09, 0x3c, 0x73, 0x80, 0xf7, 0x98, 0xfc, 0xa9, 0x5d, 0x31, 0x8e, 0x1d,
0x4c, 0x9e, 0xbb, 0xfe, 0x37, 0x6c, 0x59, 0x55, 0xbd, 0x4e, 0x61, 0x3d, 0x0e, 0x42, 0x6b, 0x50,
0xe5, 0x8b, 0xb2, 0x2d, 0xb6, 0xa6, 0xaa, 0xce, 0xc4, 0xb5, 0x6f, 0x5b, 0x51, 0x97, 0xed, 0x0d,
0xc4, 0x92, 0xe6, 0xb8, 0xe8, 0x06, 0x9a, 0x06, 0xb0, 0xeb, 0x90, 0x7b, 0x3f, 0xfa, 0xca, 0x1c,
0x85, 0x18, 0x2d, 0xc3, 0xcc, 0x33, 0xfa, 0xc1, 0xe8, 0x57, 0x74, 0xde, 0xd0, 0xfe, 0xb2, 0x02,
0x17, 0x9f, 0xd0, 0xd5, 0xf5, 0x4d, 0xc7, 0x3a, 0x72, 0x5f, 0xf4, 0xf1, 0x20, 0xf4, 0x6d, 0x72,
0xba, 0xe5, 0x3a, 0x04, 0xbf, 0x20, 0x68, 0x07, 0x16, 0x1d, 0xc9, 0xaf, 0x21, 0xed, 0x87, 0x52,
0xa8, 0x6f, 0xb6, 0xa3, 0x25, 0xa7, 0x56, 0xa4, 0xb7, 0x9c, 0x24, 0x20, 0x40, 0x9f, 0xc7, 0xc2,
0x95, 0x44, 0xca, 0x8c, 0xc8, 0x4a, 0x44, 0xa4, 0xbf, 0xc3, 0xf8, 0x10, 0x24, 0xa4, 0xd0, 0x25,
0x81, 0xf7, 0x81, 0x6e, 0x34, 0xc3, 0x0c, 0x8c, 0x30, 0xc0, 0x3e, 0x5b, 0x69, 0x7d, 0x73, 0x29,
0x1a, 0x1c, 0xaf, 0x53, 0xaf, 0xf9, 0xa1, 0xd3, 0x0d, 0x0e, 0x03, 0xec, 0xb3, 0xed, 0x28, 0xd4,
0x6b, 0xf8, 0xae, 0x4b, 0x8e, 0x03, 0xa9, 0x52, 0x09, 0xd6, 0x19, 0x14, 0xbd, 0x0b, 0x4b, 0x41,
0xe8, 0x79, 0x23, 0x3c, 0xc6, 0x0e, 0x31, 0x47, 0xc6, 0xd0, 0x77, 0x43, 0x2f, 0x68, 0xcf, 0x6c,
0x54, 0x6e, 0x54, 0x74, 0xa4, 0x76, 0x3d, 0x62, 0x3d, 0x68, 0x1d, 0xc0, 0xf3, 0xed, 0x67, 0xf6,
0x08, 0x0f, 0xb1, 0xd5, 0x9e, 0x65, 0x44, 0x15, 0x08, 0xba, 0x0b, 0xcb, 0x01, 0x1e, 0x0c, 0xdc,
0xb1, 0x67, 0x78, 0xbe, 0x7b, 0x6c, 0x8f, 0x30, 0x37, 0xc8, 0x39, 0x66, 0x90, 0x48, 0xf4, 0xed,
0xf3, 0x2e, 0x6a, 0x9a, 0xda, 0x2f, 0xca, 0x70, 0x81, 0x09, 0x60, 0xdf, 0xb5, 0x84, 0x2e, 0xc4,
0x76, 0xbf, 0x06, 0x8d, 0x01, 0x63, 0xc8, 0xf0, 0x4c, 0x1f, 0x3b, 0x44, 0xd8, 0xfd, 0x3c, 0x07,
0xee, 0x33, 0x18, 0xda, 0x83, 0x56, 0x20, 0x54, 0x67, 0x0c, 0xb8, 0xee, 0x84, 0x84, 0xdf, 0x8a,
0x84, 0x34, 0x41, 0xcf, 0xfa, 0x42, 0x90, 0x51, 0xfc, 0x5c, 0x70, 0x1a, 0x0c, 0xc8, 0x88, 0xbb,
0x8b, 0xfa, 0xe6, 0x0f, 0x92, 0x74, 0xd2, 0x6c, 0xde, 0xe9, 0x73, 0xec, 0x1d, 0x87, 0xf8, 0xa7,
0xba, 0x1c, 0xdb, 0xb9, 0x0f, 0xf3, 0x6a, 0x07, 0x6a, 0x41, 0xe5, 0x1b, 0x7c, 0x2a, 0x96, 0x40,
0x3f, 0x63, 0xbb, 0xe4, 0x9b, 0x95, 0x37, 0xee, 0x97, 0xff, 0xa0, 0xa4, 0xf9, 0x80, 0xe2, 0x59,
0x9e, 0x62, 0x62, 0x5a, 0x26, 0x31, 0x11, 0x82, 0x69, 0xe6, 0x7e, 0x39, 0x09, 0xf6, 0x4d, 0xa9,
0x86, 0x62, 0x6b, 0xd4, 0x74, 0xfa, 0x89, 0x2e, 0x41, 0x2d, 0x32, 0x42, 0xe1, 0x83, 0x63, 0x00,
0xf5, 0x85, 0x26, 0x21, 0x78, 0xec, 0x11, 0x66, 0x10, 0x0d, 0x5d, 0x36, 0xb5, 0x7f, 0x99, 0x86,
0x56, 0x46, 0x03, 0x1f, 0x42, 0x75, 0x2c, 0xa6, 0x17, 0xb6, 0x7f, 0x31, 0x76, 0x88, 0x19, 0x0e,
0xf5, 0x08, 0x99, 0xfa, 0x1b, 0xba, 0x19, 0x95, 0xe3, 0x22, 0x6a, 0x53, 0xb5, 0x8e, 0xdc, 0xa1,
0x61, 0xd9, 0x3e, 0x1e, 0x10, 0xd7, 0x3f, 0x15, 0x5c, 0xce, 0x8f, 0xdc, 0xe1, 0xb6, 0x84, 0xa1,
0xf7, 0x00, 0x2c, 0x27, 0xa0, 0x1a, 0x3d, 0xb6, 0x87, 0x8c, 0xd7, 0xfa, 0x26, 0x8a, 0xe6, 0x8e,
0x8e, 0x04, 0xbd, 0x66, 0x39, 0x81, 0x60, 0xf6, 0x23, 0x68, 0x50, 0x17, 0x6b, 0x8c, 0xb9, 0x37,
0xe7, 0x56, 0x5c, 0xdf, 0x5c, 0x56, 0x38, 0x8e, 0x5c, 0xbd, 0x3e, 0xef, 0xc5, 0x8d, 0x00, 0x7d,
0x0a, 0xb3, 0xcc, 0xc5, 0x05, 0xed, 0x59, 0x36, 0xe6, 0x7a, 0xce, 0x2a, 0x85, 0xb6, 0x9f, 0x30,
0x3c, 0xae, 0x6c, 0x31, 0x08, 0x3d, 0x81, 0xba, 0xe9, 0x38, 0x2e, 0x31, 0xf9, 0x06, 0x9f, 0x63,
0x34, 0x6e, 0x15, 0xd3, 0xe8, 0xc6, 0xc8, 0x9c, 0x90, 0x3a, 0x1c, 0xfd, 0x08, 0x66, 0x98, 0x07,
0x68, 0x57, 0xd9, 0xaa, 0xd7, 0x27, 0x9b, 0x9f, 0xce, 0x91, 0x3b, 0x1f, 0x41, 0x5d, 0x61, 0xed,
0x3c, 0xe6, 0xd6, 0xf9, 0x0c, 0x5a, 0x69, 0x8e, 0xce, 0x65, 0xae, 0xbb, 0xb0, 0xac, 0x87, 0x4e,
0xcc, 0x98, 0x8c, 0x3f, 0xde, 0x83, 0x59, 0xa1, 0x3f, 0x6e, 0x3b, 0x6b, 0x85, 0x12, 0xd1, 0x05,
0xa2, 0xf6, 0x29, 0x5c, 0x48, 0x91, 0x12, 0xd1, 0xc9, 0x5b, 0xd0, 0xf4, 0x5c, 0xcb, 0x08, 0x38,
0xd8, 0xb0, 0x2d, 0xe9, 0x0c, 0xbc, 0x08, 0x77, 0xd7, 0xa2, 0xc3, 0xfb, 0xc4, 0xf5, 0xb2, 0xac,
0x9c, 0x6d, 0x78, 0x1b, 0x56, 0xd2, 0xc3, 0xf9, 0xf4, 0xda, 0xe7, 0xb0, 0xaa, 0xe3, 0xb1, 0xfb,
0x0c, 0xbf, 0x2e, 0xe9, 0x0e, 0xb4, 0xb3, 0x04, 0x62, 0xe2, 0x31, 0xb4, 0x4f, 0x4c, 0x12, 0x06,
0xe7, 0x23, 0x7e, 0x53, 0x25, 0x20, 0x8e, 0x4e, 0x4e, 0x07, 0x35, 0xa1, 0x6c, 0x7b, 0x62, 0x50,
0xd9, 0xf6, 0xb4, 0xcf, 0xa1, 0x16, 0x1d, 0x5a, 0x68, 0x33, 0x8e, 0x8c, 0xca, 0xaf, 0x38, 0xd9,
0xa2, 0x98, 0xe9, 0x71, 0xc6, 0x5b, 0x8b, 0x99, 0x36, 0x01, 0x22, 0x3f, 0x23, 0x4f, 0x4a, 0x94,
0xa5, 0xa7, 0x2b, 0x58, 0xda, 0xdf, 0x27, 0x9c, 0x8e, 0xc2, 0xb2, 0x15, 0xb1, 0x6c, 0x25, 0x9c,
0x50, 0xf9, 0x3c, 0x4e, 0xe8, 0x0e, 0xcc, 0x04, 0xc4, 0x24, 0xdc, 0x0d, 0x36, 0x95, 0xc5, 0x25,
0xa7, 0xc4, 0x3a, 0x47, 0x43, 0x97, 0x01, 0x06, 0x3e, 0x36, 0x09, 0xb6, 0x0c, 0x93, 0xfb, 0xc7,
0x8a, 0x5e, 0x13, 0x90, 0x2e, 0x41, 0xf7, 0x61, 0x4e, 0x46, 0x2a, 0x33, 0x8c, 0x8d, 0x8d, 0x1c,
0x82, 0x09, 0xe9, 0xeb, 0x72, 0x40, 0xbc, 0xa7, 0x67, 0x27, 0xef, 0x69, 0x31, 0x8e, 0x23, 0x2b,
0x6e, 0x69, 0xae, 0xd0, 0x2d, 0xf1, 0x11, 0x67, 0x71, 0x4b, 0xd5, 0x42, 0xb7, 0x24, 0x68, 0x4c,
0x74, 0x4b, 0xbf, 0x4f, 0x07, 0xf3, 0x14, 0xda, 0xd9, 0x0d, 0x22, 0x1c, 0xc3, 0x7b, 0x30, 0x1b,
0x30, 0xc8, 0x04, 0x27, 0x23, 0x86, 0x08, 0x44, 0xed, 0x21, 0x2c, 0xa7, 0x2c, 0x80, 0x07, 0x8a,
0x91, 0xbd, 0x94, 0xce, 0x64, 0x2f, 0xda, 0xff, 0x97, 0x54, 0xeb, 0x7d, 0x68, 0x8f, 0x08, 0xf6,
0x33, 0xd6, 0xfb, 0xbe, 0x24, 0xca, 0x4d, 0xf7, 0x72, 0x11, 0x51, 0x1e, 0xc3, 0x09, 0x4b, 0xec,
0x43, 0x93, 0xe9, 0xd0, 0x08, 0xf0, 0x88, 0x1d, 0x88, 0x22, 0x14, 0xf9, 0x61, 0xce, 0x68, 0x3e,
0x2f, 0x37, 0x80, 0xbe, 0x40, 0xe7, 0xea, 0x6b, 0x8c, 0x54, 0x58, 0xe7, 0x01, 0xa0, 0x2c, 0xd2,
0xb9, 0xf4, 0xf0, 0x25, 0xdd, 0xfb, 0x34, 0x71, 0xc9, 0xf1, 0xf4, 0xc7, 0x8c, 0x8d, 0x09, 0x4a,
0xe0, 0x7c, 0xea, 0x02, 0x51, 0xfb, 0xbb, 0x0a, 0x40, 0xdc, 0xf9, 0xc6, 0x6e, 0xfa, 0x0f, 0xa3,
0x2d, 0xc8, 0xa3, 0x89, 0x2b, 0x39, 0xf4, 0x72, 0x37, 0xdf, 0xc3, 0xe4, 0xe6, 0xe3, 0x71, 0xc5,
0x5b, 0x79, 0xa3, 0xdf, 0xd8, 0x6d, 0xb7, 0x05, 0x2b, 0x69, 0x75, 0x8b, 0x4d, 0x77, 0x13, 0x66,
0x6c, 0x82, 0xc7, 0x3c, 0x0d, 0x57, 0xd3, 0x11, 0x05, 0x97, 0x63, 0x68, 0x57, 0xa1, 0xb6, 0x3b,
0x36, 0x87, 0xb8, 0xef, 0xe1, 0x01, 0x9d, 0xcb, 0xa6, 0x0d, 0x31, 0x3f, 0x6f, 0x68, 0x9b, 0x50,
0x7d, 0x8c, 0x4f, 0xf9, 0x1e, 0x3c, 0x23, 0x7f, 0xda, 0x5f, 0x97, 0x61, 0x95, 0xf9, 0xce, 0x2d,
0x99, 0x04, 0xeb, 0x38, 0x70, 0x43, 0x7f, 0x80, 0x03, 0xa6, 0x52, 0x2f, 0x34, 0x3c, 0xec, 0xdb,
0xae, 0x25, 0xb2, 0xbe, 0xda, 0xc0, 0x0b, 0xf7, 0x19, 0x80, 0x26, 0xca, 0xb4, 0xfb, 0xdb, 0xd0,
0x15, 0xb6, 0x55, 0xd1, 0xab, 0x03, 0x2f, 0xfc, 0x31, 0x6d, 0xcb, 0xb1, 0xc1, 0x89, 0xe9, 0xe3,
0x80, 0xd9, 0x10, 0x1f, 0xdb, 0x67, 0x00, 0xf4, 0x1e, 0x5c, 0x18, 0xe3, 0xb1, 0xeb, 0x9f, 0x1a,
0x23, 0x7b, 0x6c, 0x13, 0xc3, 0x76, 0x8c, 0xa3, 0x53, 0x82, 0x03, 0x61, 0x38, 0x88, 0x77, 0x3e,
0xa1, 0x7d, 0xbb, 0xce, 0x17, 0xb4, 0x07, 0x69, 0xd0, 0x70, 0xdd, 0xb1, 0x11, 0x0c, 0x5c, 0x1f,
0x1b, 0xa6, 0xf5, 0x35, 0x3b, 0x3c, 0x2a, 0x7a, 0xdd, 0x75, 0xc7, 0x7d, 0x0a, 0xeb, 0x5a, 0x5f,
0xa3, 0x2b, 0x50, 0x1f, 0x78, 0x61, 0x80, 0x89, 0x41, 0x7f, 0xd8, 0x21, 0x51, 0xd3, 0x81, 0x83,
0xb6, 0xbc, 0x30, 0x50, 0x10, 0xc6, 0x54, 0xec, 0x73, 0x2a, 0xc2, 0x53, 0x2a, 0x66, 0x13, 0x1a,
0x89, 0x3c, 0x92, 0x66, 0x0b, 0x2c, 0x61, 0x14, 0xd9, 0x02, 0xfd, 0xa6, 0x30, 0xdf, 0x1d, 0x49,
0x49, 0xb2, 0x6f, 0x0a, 0x23, 0xa7, 0x9e, 0x4c, 0x15, 0xd8, 0x37, 0x15, 0xf9, 0x08, 0x3f, 0x13,
0x75, 0x80, 0x9a, 0xce, 0x1b, 0x9a, 0x05, 0xb0, 0x65, 0x7a, 0xe6, 0x91, 0x3d, 0xb2, 0xc9, 0x29,
0xba, 0x09, 0x2d, 0xd3, 0xb2, 0x8c, 0x81, 0x84, 0xd8, 0x58, 0x16, 0x65, 0x16, 0x4c, 0xcb, 0xda,
0x52, 0xc0, 0xe8, 0x07, 0xb0, 0x68, 0xf9, 0xae, 0x97, 0xc4, 0xe5, 0x55, 0x9a, 0x16, 0xed, 0x50,
0x91, 0xb5, 0x7f, 0x9e, 0x86, 0xcb, 0x49, 0xc5, 0xa6, 0x33, 0xf3, 0x0f, 0x61, 0x3e, 0x35, 0x6b,
0x32, 0x25, 0x8e, 0x99, 0xd4, 0x13, 0x88, 0xa9, 0xdc, 0xb5, 0x9c, 0xc9, 0x5d, 0x73, 0x53, 0xfe,
0xca, 0xf7, 0x91, 0xf2, 0x4f, 0x7f, 0x97, 0x94, 0x7f, 0xe6, 0x4c, 0x29, 0xff, 0xdb, 0xac, 0x02,
0x27, 0x07, 0xb1, 0xc4, 0x8b, 0x9b, 0x51, 0x23, 0xc2, 0x71, 0x64, 0xa5, 0x2e, 0x55, 0x1a, 0x98,
0x3b, 0x4f, 0x69, 0xa0, 0x5a, 0x58, 0x1a, 0xa0, 0x16, 0xe1, 0x79, 0xa6, 0x3f, 0x76, 0x7d, 0x99,
0xfb, 0xb7, 0x6b, 0x8c, 0x85, 0x05, 0x09, 0x17, 0x79, 0x7f, 0x61, 0x95, 0x00, 0x8a, 0xaa, 0x04,
0x68, 0x03, 0xe6, 0x1d, 0xd7, 0x70, 0xf0, 0x73, 0x83, 0x2a, 0x2c, 0x68, 0xd7, 0xb9, 0xf6, 0x1c,
0xb7, 0x87, 0x9f, 0xef, 0x53, 0x88, 0xf6, 0x0f, 0x25, 0x58, 0x4e, 0x1a, 0x8e, 0xc8, 0x0b, 0x3f,
0x83, 0x9a, 0x2f, 0x7d, 0x83, 0x30, 0x96, 0x8d, 0x64, 0xfc, 0x95, 0xf5, 0x21, 0x7a, 0x3c, 0x04,
0xfd, 0xb8, 0xb0, 0xc2, 0xf0, 0x76, 0x01, 0x99, 0x57, 0xd5, 0x18, 0xb4, 0x2e, 0x2c, 0x46, 0xc8,
0x13, 0xf3, 0x7b, 0x25, 0x5f, 0x2f, 0x27, 0xf3, 0x75, 0x07, 0x66, 0xb7, 0xf1, 0x33, 0x7b, 0x80,
0xbf, 0x97, 0xfa, 0xe0, 0x06, 0xd4, 0x3d, 0xec, 0x8f, 0xed, 0x20, 0x88, 0x8c, 0xbe, 0xa6, 0xab,
0x20, 0xed, 0xbf, 0x66, 0x60, 0x21, 0x2d, 0xd9, 0x7b, 0x99, 0xf2, 0x40, 0x27, 0xde, 0x85, 0xe9,
0xf5, 0x29, 0x67, 0xf4, 0x0d, 0x79, 0x0c, 0x94, 0x53, 0x59, 0x42, 0x74, 0x52, 0x88, 0xa3, 0x81,
0xae, 0x7f, 0xe0, 0x8e, 0xc7, 0xa6, 0x63, 0xc9, 0xda, 0xad, 0x68, 0x52, 0x69, 0x99, 0xfe, 0x90,
0x6e, 0x2d, 0x0a, 0x66, 0xdf, 0xd4, 0x4b, 0xd2, 0x68, 0xdb, 0x76, 0x58, 0x75, 0x81, 0x6d, 0x9c,
0x9a, 0x0e, 0x02, 0xb4, 0x6d, 0xfb, 0xe8, 0x3a, 0x4c, 0x63, 0xe7, 0x99, 0x3c, 0x8d, 0xe3, 0xe2,
0xae, 0x3c, 0x7e, 0x74, 0xd6, 0x8d, 0xde, 0x86, 0xd9, 0xb1, 0x1b, 0x3a, 0x44, 0xc6, 0xdd, 0xcd,
0x64, 0x8d, 0x53, 0x17, 0xbd, 0xe8, 0x26, 0xcc, 0x59, 0x4c, 0x07, 0x32, 0xb8, 0x5e, 0x88, 0x2b,
0x14, 0x0c, 0xae, 0xcb, 0x7e, 0xf4, 0x49, 0x14, 0x47, 0xd4, 0x52, 0x91, 0x40, 0x4a, 0xa8, 0xb9,
0xc1, 0xc4, 0xe3, 0x64, 0x30, 0x01, 0x8c, 0xc4, 0xcd, 0x42, 0x12, 0x93, 0xeb, 0x0b, 0x6b, 0x50,
0x1d, 0xb9, 0x43, 0x6e, 0x07, 0x75, 0x5e, 0xe9, 0x1f, 0xb9, 0x43, 0x66, 0x06, 0xcb, 0x34, 0x78,
0xb2, 0x6c, 0xa7, 0x3d, 0xcf, 0xb6, 0x17, 0x6f, 0xd0, 0x33, 0x91, 0x7d, 0x18, 0xae, 0x33, 0xc0,
0xed, 0x06, 0xeb, 0xaa, 0x31, 0xc8, 0x9e, 0x33, 0x60, 0x47, 0x36, 0x21, 0xa7, 0xed, 0x26, 0x83,
0xd3, 0x4f, 0x1a, 0xf3, 0xf2, 0x6c, 0x67, 0x21, 0x15, 0xf3, 0xe6, 0xed, 0xcf, 0x37, 0xa0, 0x80,
0xf1, 0x4f, 0x25, 0x58, 0xd9, 0x62, 0x21, 0x9f, 0xe2, 0x09, 0xce, 0x91, 0x80, 0xa3, 0xbb, 0x51,
0xa5, 0x23, 0x9d, 0x47, 0xa7, 0x17, 0x2b, 0xf0, 0xd0, 0x03, 0x68, 0x4a, 0x9a, 0x62, 0x64, 0xe5,
0x55, 0x35, 0x92, 0x46, 0xa0, 0x36, 0xb5, 0x4f, 0x60, 0x35, 0xc3, 0xb3, 0x08, 0xcf, 0xae, 0xc2,
0x7c, 0xec, 0x11, 0x22, 0x96, 0xeb, 0x11, 0x6c, 0xd7, 0xd2, 0xee, 0xc3, 0x85, 0x3e, 0x31, 0x7d,
0x92, 0x59, 0xf0, 0x19, 0xc6, 0xb2, 0x32, 0x49, 0x72, 0xac, 0xa8, 0x64, 0xf4, 0x61, 0xb9, 0x4f,
0x5c, 0xef, 0x35, 0x88, 0xd2, 0x9d, 0x4e, 0x97, 0xed, 0x86, 0x44, 0xc4, 0x64, 0xb2, 0xa9, 0xad,
0xf2, 0xa2, 0x4e, 0x76, 0xb6, 0x8f, 0x61, 0x85, 0xd7, 0x54, 0x5e, 0x67, 0x11, 0x6b, 0xb2, 0xa2,
0x93, 0xa5, 0xbb, 0x0d, 0x4b, 0xb1, 0x2b, 0x8f, 0xd3, 0xc3, 0xdb, 0xc9, 0xf4, 0x70, 0x35, 0xab,
0xe3, 0x44, 0x76, 0xf8, 0x37, 0x65, 0xc5, 0x61, 0x16, 0x24, 0x87, 0x9b, 0xc9, 0xe4, 0xf0, 0x52,
0x01, 0xc9, 0x44, 0x6e, 0x98, 0xb5, 0xc8, 0x4a, 0x8e, 0x45, 0xea, 0x99, 0x0c, 0x72, 0x3a, 0x55,
0xcc, 0x4e, 0xf1, 0xf6, 0x3b, 0x49, 0x20, 0x77, 0x79, 0x02, 0x19, 0x4d, 0x1d, 0xd5, 0xb9, 0xee,
0xa6, 0x12, 0xc8, 0x76, 0x11, 0x9b, 0x51, 0xfe, 0xf8, 0x57, 0xd3, 0x50, 0x8b, 0xfa, 0x32, 0x82,
0xcd, 0x0a, 0xa9, 0x9c, 0x23, 0x24, 0xf5, 0xfc, 0xaa, 0xbc, 0xce, 0xf9, 0x35, 0xfd, 0xaa, 0xf3,
0xeb, 0x22, 0xd4, 0xd8, 0x87, 0xe1, 0xe3, 0x63, 0x71, 0x1e, 0x55, 0x19, 0x40, 0xc7, 0xc7, 0xb1,
0x41, 0xcd, 0x9e, 0xc5, 0xa0, 0x52, 0x99, 0xea, 0x5c, 0x3a, 0x53, 0xbd, 0x17, 0x9d, 0x30, 0xfc,
0x2c, 0x5a, 0xcf, 0x92, 0xcb, 0x3d, 0x5b, 0x76, 0x92, 0x67, 0x0b, 0x3f, 0x9e, 0xae, 0xe5, 0x0c,
0x7e, 0x63, 0xf3, 0xd4, 0x27, 0x3c, 0x4f, 0x55, 0xad, 0x4a, 0x38, 0xc2, 0x4d, 0x80, 0x68, 0xcf,
0xcb, 0x64, 0x15, 0x65, 0x97, 0xa6, 0x2b, 0x58, 0xd4, 0xab, 0x24, 0xe4, 0x1f, 0x17, 0x63, 0xcf,
0xe0, 0x55, 0xfe, 0x55, 0x8d, 0x92, 0x0a, 0xea, 0x99, 0xf7, 0x32, 0xa5, 0x8d, 0xb3, 0x59, 0xdd,
0xed, 0x64, 0x65, 0xe3, 0x7c, 0xe6, 0x92, 0x29, 0x6c, 0xb0, 0x43, 0xdd, 0xf4, 0x45, 0x37, 0xcf,
0x49, 0x6b, 0x02, 0xd2, 0x25, 0x34, 0x94, 0x3a, 0xb6, 0x1d, 0x3b, 0x38, 0xe1, 0xfd, 0xb3, 0xac,
0x1f, 0x24, 0xa8, 0xcb, 0x6e, 0xb5, 0xf1, 0x0b, 0x9b, 0x18, 0x03, 0xd7, 0xc2, 0xcc, 0x18, 0x67,
0xf4, 0x2a, 0x05, 0x6c, 0xb9, 0x16, 0x8e, 0x37, 0x48, 0xf5, 0x5c, 0x1b, 0xa4, 0x96, 0xda, 0x20,
0x2b, 0x30, 0xeb, 0x63, 0x33, 0x70, 0x1d, 0x91, 0x18, 0x88, 0x16, 0x3d, 0x2b, 0xc6, 0x38, 0x08,
0xe8, 0x04, 0x22, 0x80, 0x11, 0x4d, 0x25, 0xcc, 0x9a, 0x2f, 0x0a, 0xb3, 0x26, 0x14, 0x4c, 0x53,
0x61, 0x56, 0xa3, 0x28, 0xcc, 0x3a, 0x4b, 0xbd, 0x54, 0x09, 0x22, 0x9b, 0x13, 0x83, 0x48, 0x35,
0x1c, 0x5b, 0x48, 0x84, 0x63, 0xbf, 0xcf, 0x3d, 0xf5, 0x18, 0x56, 0x33, 0xbb, 0x40, 0x6c, 0xaa,
0xbb, 0xa9, 0x8a, 0x6b, 0xbb, 0x48, 0x40, 0x51, 0xc1, 0xf5, 0xcf, 0xe0, 0xca, 0xa1, 0x67, 0xa5,
0x42, 0x15, 0x91, 0x68, 0x9d, 0x3d, 0x42, 0xb8, 0x27, 0xa3, 0xca, 0xf2, 0x19, 0x73, 0x38, 0x8e,
0xae, 0x69, 0xb0, 0x51, 0x3c, 0xbb, 0x38, 0xf2, 0xff, 0x04, 0x16, 0x76, 0x5e, 0xe0, 0x41, 0xff,
0xd4, 0x19, 0x9c, 0x83, 0xa3, 0x16, 0x54, 0x06, 0x63, 0x4b, 0x94, 0x32, 0xe8, 0xa7, 0x1a, 0xc5,
0x54, 0x92, 0x51, 0x8c, 0x01, 0xad, 0x78, 0x06, 0x21, 0xc9, 0x15, 0x2a, 0x49, 0x8b, 0x22, 0x53,
0xe2, 0xf3, 0xba, 0x68, 0x09, 0x38, 0xf6, 0x7d, 0xb6, 0x54, 0x0e, 0xc7, 0xbe, 0x9f, 0xdc, 0x73,
0x95, 0xe4, 0x9e, 0xd3, 0xbe, 0x86, 0x3a, 0x9d, 0xe0, 0x3b, 0xb1, 0x2f, 0x42, 0xf9, 0x4a, 0x1c,
0xca, 0x47, 0x19, 0xc1, 0xb4, 0x92, 0x11, 0x68, 0x1b, 0x30, 0xcf, 0xe7, 0x12, 0x0b, 0x69, 0x41,
0x25, 0xf4, 0x47, 0xd2, 0xb2, 0x42, 0x7f, 0xa4, 0xfd, 0x11, 0x34, 0xba, 0x84, 0x98, 0x83, 0x93,
0x73, 0xf0, 0x13, 0xcd, 0x55, 0x56, 0xb3, 0x8f, 0x0c, 0x4f, 0x9a, 0x06, 0x4d, 0x49, 0xbb, 0x70,
0xfe, 0x1e, 0xa0, 0x7d, 0xd7, 0x27, 0x0f, 0x5d, 0xff, 0xb9, 0xe9, 0x5b, 0xe7, 0x8b, 0xe6, 0x11,
0x4c, 0x8b, 0xd7, 0x3c, 0x95, 0x1b, 0x33, 0x3a, 0xfb, 0xd6, 0xde, 0x81, 0xa5, 0x04, 0xbd, 0xc2,
0x89, 0x3f, 0x84, 0x3a, 0x73, 0x72, 0x22, 0xe2, 0xbb, 0xa1, 0x56, 0x3c, 0x27, 0x79, 0x42, 0xad,
0x0b, 0x8b, 0xf4, 0x14, 0x63, 0xf0, 0x68, 0x5b, 0xfc, 0x30, 0x15, 0x17, 0x2d, 0x27, 0xc7, 0xa7,
0x62, 0xa2, 0x7f, 0x2c, 0xc1, 0x0c, 0x83, 0x67, 0xce, 0x9c, 0x8b, 0x50, 0xf3, 0xb1, 0xe7, 0x1a,
0xc4, 0x1c, 0x46, 0x0f, 0xa4, 0x28, 0xe0, 0xc0, 0x1c, 0x06, 0xec, 0x7d, 0x17, 0xed, 0xb4, 0xec,
0x21, 0x0e, 0x88, 0x7c, 0x25, 0x55, 0xa7, 0xb0, 0x6d, 0x0e, 0xa2, 0x22, 0x09, 0xec, 0x3f, 0xe5,
0x01, 0xcf, 0xb4, 0xce, 0xbe, 0xd1, 0x75, 0xfe, 0xf6, 0x60, 0x42, 0x79, 0x8a, 0x3d, 0x48, 0xe8,
0x40, 0x35, 0x55, 0x91, 0x8a, 0xda, 0xda, 0x27, 0x80, 0xd4, 0x35, 0x0b, 0xa1, 0xbe, 0x0d, 0xb3,
0x4c, 0x24, 0xf2, 0xc4, 0x6e, 0x26, 0x17, 0xad, 0x8b, 0x5e, 0xed, 0x33, 0x40, 0x5c, 0x8a, 0x89,
0x53, 0xfa, 0xec, 0x12, 0xff, 0x18, 0x96, 0x12, 0xe3, 0xa3, 0xab, 0xe6, 0x04, 0x81, 0xf4, 0xec,
0x62, 0xf0, 0xaf, 0x4b, 0x00, 0xdd, 0x90, 0x9c, 0x88, 0x52, 0x88, 0xba, 0xca, 0x52, 0x72, 0x95,
0xb4, 0xcf, 0x33, 0x83, 0xe0, 0xb9, 0xeb, 0xcb, 0x30, 0x34, 0x6a, 0xb3, 0x32, 0x46, 0x48, 0x4e,
0x64, 0xf9, 0x95, 0x7e, 0xa3, 0xeb, 0xd0, 0xe4, 0xef, 0xda, 0x0c, 0xd3, 0xb2, 0x7c, 0x1c, 0x04,
0xa2, 0x0e, 0xdb, 0xe0, 0xd0, 0x2e, 0x07, 0x52, 0x34, 0xdb, 0xc2, 0x0e, 0xb1, 0xc9, 0xa9, 0x41,
0xdc, 0x6f, 0xb0, 0x23, 0x02, 0xcc, 0x86, 0x84, 0x1e, 0x50, 0x20, 0x45, 0xf3, 0xf1, 0xd0, 0x0e,
0x88, 0x2f, 0xd1, 0x64, 0x5d, 0x50, 0x40, 0x19, 0x9a, 0xf6, 0xcb, 0x12, 0xb4, 0xf6, 0xc3, 0xd1,
0x88, 0x2f, 0xf2, 0xbc, 0xb2, 0x44, 0xef, 0x88, 0x75, 0x94, 0x53, 0xd6, 0x10, 0x8b, 0x48, 0x2c,
0xee, 0xbb, 0x27, 0xbe, 0x77, 0x61, 0x51, 0x61, 0x54, 0x28, 0x2d, 0x11, 0x47, 0x94, 0x92, 0x71,
0x04, 0x35, 0x14, 0x9e, 0xeb, 0xbd, 0xde, 0xe2, 0xb4, 0x0b, 0xb0, 0x94, 0x18, 0x2f, 0x0e, 0x8d,
0x5b, 0xd0, 0x10, 0xd7, 0xbd, 0xc2, 0x08, 0xd6, 0xa0, 0x4a, 0xdd, 0xcb, 0xc0, 0xb6, 0x64, 0xdd,
0x7d, 0xce, 0x73, 0xad, 0x2d, 0xdb, 0xf2, 0xb5, 0x1e, 0x34, 0x74, 0x4e, 0x5e, 0xe0, 0x7e, 0x0a,
0x4d, 0x71, 0x39, 0x6c, 0x24, 0x1e, 0x49, 0xc4, 0x45, 0xe2, 0x04, 0x6d, 0xbd, 0xe1, 0xa8, 0x4d,
0xed, 0xe7, 0xd0, 0xe1, 0x87, 0x5a, 0x82, 0xaa, 0x5c, 0xda, 0xa7, 0x20, 0xdf, 0x5d, 0x16, 0x11,
0x4f, 0x0e, 0x6b, 0xf8, 0x6a, 0x53, 0xbb, 0x0c, 0x17, 0x73, 0x89, 0x8b, 0x75, 0x7b, 0xd0, 0x8a,
0x3b, 0x2c, 0x5b, 0x5e, 0x37, 0xb0, 0x6b, 0x84, 0x92, 0x72, 0x8d, 0xb0, 0x12, 0x05, 0x0a, 0xdc,
0xa1, 0x8b, 0x96, 0x12, 0xd6, 0x55, 0x8a, 0xc2, 0xba, 0xe9, 0x44, 0x58, 0xa7, 0x7d, 0x19, 0x49,
0x4f, 0xc4, 0xd4, 0x1f, 0xb1, 0xc0, 0x9e, 0xcf, 0x2d, 0xdd, 0xc4, 0x5a, 0xce, 0xe2, 0x38, 0x86,
0xae, 0x20, 0x6b, 0x0b, 0xd0, 0x48, 0x38, 0x0c, 0xed, 0x01, 0x34, 0x53, 0x1e, 0xe0, 0x4e, 0x2a,
0xc2, 0xc9, 0x88, 0x2d, 0x15, 0xdf, 0x2c, 0x0b, 0x47, 0xf4, 0x30, 0xd8, 0x75, 0x8e, 0x5d, 0x49,
0xf7, 0x1a, 0xd4, 0x0f, 0x8b, 0x9e, 0x21, 0x4e, 0xcb, 0x7b, 0xac, 0x77, 0x60, 0xb1, 0x4f, 0x5c,
0xdf, 0x1c, 0xe2, 0x5d, 0xb6, 0x6b, 0x8f, 0x6d, 0x7e, 0x4f, 0x13, 0x86, 0x91, 0xff, 0x66, 0xdf,
0xda, 0x7f, 0x94, 0x60, 0xe1, 0xa1, 0x3d, 0xc2, 0xc1, 0x69, 0x40, 0xf0, 0xf8, 0x90, 0x45, 0xbb,
0x97, 0xa0, 0x46, 0xb9, 0x09, 0x88, 0x39, 0xf6, 0xe4, 0x3d, 0x57, 0x04, 0xa0, 0x32, 0x0a, 0x38,
0x69, 0x99, 0xff, 0xaa, 0x99, 0x46, 0x66, 0x56, 0x1a, 0xfd, 0x0b, 0x10, 0x7a, 0x1f, 0x20, 0x0c,
0xb0, 0x25, 0xee, 0xb6, 0x2a, 0xa9, 0xa3, 0xe7, 0x50, 0xbd, 0x81, 0xa0, 0x78, 0xfc, 0xa2, 0xeb,
0x03, 0xa8, 0xdb, 0x8e, 0x6b, 0x61, 0x76, 0x03, 0x61, 0x89, 0xdc, 0x38, 0x7f, 0x14, 0x70, 0xc4,
0xc3, 0x00, 0x5b, 0xda, 0x1f, 0x0b, 0x2f, 0x2c, 0x85, 0x27, 0x74, 0xb0, 0x03, 0x8b, 0x7c, 0x43,
0x1f, 0x47, 0x8b, 0x96, 0x8a, 0x8e, 0x03, 0xce, 0x94, 0x40, 0xf4, 0x96, 0x2d, 0x4e, 0x45, 0x39,
0x42, 0xbb, 0x0f, 0x17, 0x12, 0x51, 0xe9, 0x79, 0x92, 0xb9, 0x47, 0xa9, 0x4c, 0x30, 0x36, 0x10,
0x91, 0x8a, 0x49, 0xfb, 0x28, 0x48, 0xc5, 0x02, 0x9e, 0x8a, 0x05, 0x9a, 0x0e, 0x6b, 0x89, 0x04,
0x35, 0xc1, 0xc8, 0x07, 0xa9, 0x23, 0xfe, 0x72, 0x01, 0xb1, 0xd4, 0x59, 0xff, 0xbf, 0x25, 0x58,
0xce, 0x43, 0x78, 0xcd, 0x52, 0xc8, 0x4f, 0x0a, 0x5e, 0x1c, 0xdc, 0x9d, 0xc8, 0xcd, 0xef, 0xa4,
0x68, 0xf4, 0x18, 0x3a, 0x79, 0xd2, 0xcb, 0xaa, 0xa2, 0x72, 0x06, 0x55, 0xfc, 0x5f, 0x59, 0x29,
0xee, 0x75, 0x09, 0xf1, 0xed, 0xa3, 0x90, 0x1a, 0xef, 0xf7, 0x95, 0xa4, 0x3f, 0x88, 0x12, 0x50,
0x2e, 0xbf, 0x1b, 0xd9, 0x51, 0xf1, 0xac, 0xb9, 0x49, 0xe8, 0x5e, 0x32, 0x09, 0xe5, 0x65, 0xbb,
0xdb, 0x13, 0xc9, 0xbc, 0xb1, 0x95, 0x99, 0x97, 0x25, 0x68, 0x26, 0xf5, 0x80, 0x3e, 0x01, 0x30,
0x23, 0xce, 0x85, 0xc9, 0x5f, 0x9a, 0xb4, 0x3a, 0x5d, 0xc1, 0x47, 0xd7, 0xa0, 0x32, 0xf0, 0x42,
0xa1, 0x91, 0xf8, 0xfe, 0x66, 0xcb, 0x0b, 0xb9, 0x03, 0xa0, 0xbd, 0x34, 0x68, 0xe6, 0xf7, 0xf0,
0x19, 0xcf, 0xf5, 0x94, 0x81, 0x39, 0xaa, 0xc0, 0x41, 0x9f, 0x43, 0xf3, 0xb9, 0x6f, 0x13, 0xf3,
0x68, 0x84, 0x8d, 0x91, 0x79, 0x8a, 0x7d, 0xe1, 0xb9, 0x8a, 0xbd, 0x4c, 0x43, 0xe2, 0x3f, 0xa1,
0xe8, 0x5a, 0x08, 0x55, 0x39, 0xff, 0x2b, 0x3c, 0xf2, 0x63, 0x58, 0x0d, 0x29, 0x9a, 0xc1, 0xde,
0x02, 0x38, 0xa6, 0xe3, 0x1a, 0x01, 0xa6, 0x47, 0x93, 0x7c, 0x7f, 0x97, 0xef, 0x2d, 0x97, 0xd9,
0xa0, 0x2d, 0xd7, 0xc7, 0x3d, 0xd3, 0x71, 0xfb, 0x7c, 0x84, 0x36, 0x86, 0xba, 0xb2, 0x9c, 0x57,
0xcc, 0xfc, 0x00, 0x16, 0xe5, 0xcd, 0x58, 0x80, 0x89, 0xf0, 0xeb, 0x93, 0xe6, 0x5c, 0x10, 0xe8,
0x7d, 0x4c, 0x98, 0x77, 0xbf, 0x75, 0x09, 0xaa, 0xf2, 0x2f, 0x10, 0x68, 0x0e, 0x2a, 0x07, 0x5b,
0xfb, 0xad, 0x29, 0xfa, 0x71, 0xb8, 0xbd, 0xdf, 0x2a, 0xdd, 0x1a, 0x43, 0x2b, 0xfd, 0xfc, 0x1f,
0xad, 0xc2, 0xd2, 0xbe, 0xbe, 0xb7, 0xdf, 0x7d, 0xd4, 0x3d, 0xd8, 0xdd, 0xeb, 0x19, 0xfb, 0xfa,
0xee, 0x57, 0xdd, 0x83, 0x9d, 0xd6, 0x14, 0xba, 0x0a, 0x97, 0xd5, 0x8e, 0x3f, 0xdc, 0xeb, 0x1f,
0x18, 0x07, 0x7b, 0xc6, 0xd6, 0x5e, 0xef, 0xa0, 0xbb, 0xdb, 0xdb, 0xd1, 0x5b, 0x25, 0x74, 0x19,
0xd6, 0x54, 0x94, 0x2f, 0x76, 0xb7, 0x77, 0xf5, 0x9d, 0x2d, 0xfa, 0xdd, 0x7d, 0xd2, 0x2a, 0xdf,
0xba, 0x0f, 0x0b, 0xa9, 0xe7, 0x3c, 0x68, 0x11, 0x1a, 0xfd, 0x6e, 0x6f, 0xfb, 0x8b, 0xbd, 0x9f,
0x1a, 0xfa, 0x4e, 0x77, 0xfb, 0x67, 0xad, 0x29, 0xb4, 0x0c, 0x2d, 0x09, 0xea, 0xed, 0x1d, 0x70,
0x68, 0xe9, 0xd6, 0x37, 0x29, 0x93, 0xc4, 0xe8, 0x02, 0x2c, 0x46, 0x73, 0x1b, 0x5b, 0xfa, 0x4e,
0xf7, 0x60, 0x67, 0xbb, 0x35, 0x95, 0x04, 0xeb, 0x87, 0xbd, 0xde, 0x6e, 0xef, 0x51, 0xab, 0x44,
0xa9, 0xc6, 0xe0, 0x9d, 0x9f, 0xee, 0x52, 0xe4, 0x72, 0x12, 0xf9, 0xb0, 0xf7, 0xb8, 0xb7, 0xf7,
0x93, 0x5e, 0xab, 0xb2, 0xf9, 0xef, 0x0d, 0x68, 0xca, 0x98, 0x01, 0xfb, 0xec, 0xba, 0xf6, 0x33,
0x98, 0x93, 0x7f, 0x86, 0x89, 0x9d, 0x55, 0xf2, 0x9f, 0x3b, 0x9d, 0x76, 0xb6, 0x43, 0xc4, 0x5e,
0x53, 0x68, 0x9f, 0xc5, 0x42, 0xca, 0xd3, 0xa9, 0xcb, 0x6a, 0x74, 0x92, 0x79, 0x9b, 0xd5, 0x59,
0x2f, 0xea, 0x8e, 0x28, 0xf6, 0x69, 0x00, 0xa4, 0x3e, 0x7b, 0x45, 0xeb, 0x6a, 0x98, 0x90, 0x7d,
0x4e, 0xdb, 0xb9, 0x52, 0xd8, 0x1f, 0x11, 0xfd, 0x19, 0xb4, 0xd2, 0x0f, 0x5e, 0x51, 0x5c, 0xb2,
0x29, 0x78, 0x4c, 0xdb, 0xb9, 0x3a, 0x01, 0x43, 0x25, 0x9d, 0x79, 0x34, 0xba, 0x51, 0xfc, 0xec,
0x2f, 0x43, 0xba, 0xe8, 0x2d, 0x21, 0x17, 0x45, 0xf2, 0xc9, 0x13, 0x52, 0x9f, 0x6a, 0xe6, 0x3c,
0x7d, 0x53, 0x44, 0x91, 0xff, 0x56, 0x4a, 0x9b, 0x42, 0x5f, 0xc1, 0x42, 0xea, 0xa6, 0x0e, 0xc5,
0xa3, 0xf2, 0xef, 0x1d, 0x3b, 0x1b, 0xc5, 0x08, 0x49, 0xbd, 0xa9, 0xf7, 0x70, 0x09, 0xbd, 0xe5,
0x5c, 0xee, 0x25, 0xf4, 0x96, 0x7b, 0x81, 0xc7, 0xcc, 0x2b, 0x71, 0xdb, 0xa6, 0x98, 0x57, 0xde,
0xd5, 0x5e, 0x67, 0xbd, 0xa8, 0x5b, 0x5d, 0x7e, 0xea, 0xa6, 0x4d, 0x59, 0x7e, 0xfe, 0x05, 0x5e,
0x67, 0xa3, 0x18, 0x21, 0xad, 0xab, 0xb8, 0xec, 0x9f, 0xd2, 0x55, 0xe6, 0x96, 0x29, 0xa5, 0xab,
0xec, 0x7d, 0x81, 0xd0, 0x55, 0xaa, 0x7e, 0x7f, 0xa5, 0xb0, 0xbe, 0x99, 0xd5, 0x55, 0x7e, 0xc9,
0x54, 0x9b, 0x42, 0xdf, 0x42, 0xbb, 0xa8, 0x08, 0x89, 0xe2, 0x18, 0xe1, 0x15, 0x55, 0xd2, 0xce,
0xcd, 0x33, 0x60, 0x46, 0x53, 0x76, 0xa1, 0x2a, 0x2b, 0x8e, 0x28, 0x76, 0x28, 0xa9, 0x32, 0x67,
0x67, 0x2d, 0xa7, 0x27, 0x22, 0xf1, 0x01, 0x4c, 0x53, 0x28, 0x5a, 0x4e, 0x20, 0xc9, 0xa1, 0x17,
0x52, 0xd0, 0x68, 0xd8, 0xc7, 0x30, 0xcb, 0x0b, 0x74, 0x28, 0xce, 0x9c, 0x12, 0xd5, 0xc0, 0xce,
0x6a, 0x06, 0x1e, 0x0d, 0xfe, 0x92, 0xff, 0x27, 0x4f, 0x54, 0xda, 0xd0, 0xc5, 0xc4, 0xdf, 0x37,
0x92, 0xf5, 0xbc, 0xce, 0xa5, 0xfc, 0x4e, 0xd5, 0x44, 0x52, 0xe1, 0xc7, 0x7a, 0x51, 0x7c, 0x98,
0x31, 0x91, 0xfc, 0x78, 0x53, 0x9b, 0x42, 0x06, 0x2f, 0x5a, 0xa5, 0x08, 0x6b, 0xf9, 0xb6, 0x95,
0x20, 0x7e, 0x6d, 0x22, 0x4e, 0x34, 0xc1, 0x11, 0x2c, 0xe5, 0xa4, 0xdf, 0xe8, 0x5a, 0x4a, 0xf9,
0x79, 0x99, 0x7f, 0xe7, 0xad, 0xc9, 0x48, 0xaa, 0x8a, 0x84, 0x79, 0xaf, 0xa8, 0x3e, 0x41, 0xb1,
0xea, 0xd5, 0x0c, 0x5c, 0x0e, 0xde, 0xfc, 0x8b, 0x0a, 0xcc, 0xf3, 0x22, 0x89, 0x38, 0xd3, 0x1e,
0x01, 0xc4, 0x75, 0x3c, 0xd4, 0x49, 0x2c, 0x33, 0x51, 0xd0, 0xec, 0x5c, 0xcc, 0xed, 0x53, 0x95,
0xaf, 0x94, 0xe4, 0x14, 0xe5, 0x67, 0x0b, 0x7d, 0x8a, 0xf2, 0x73, 0xaa, 0x78, 0xda, 0x14, 0xda,
0x86, 0x5a, 0x54, 0x27, 0x42, 0x4a, 0x79, 0x29, 0x55, 0xe4, 0xea, 0x74, 0xf2, 0xba, 0x54, 0x8e,
0x94, 0xda, 0x8f, 0xc2, 0x51, 0xb6, 0xa2, 0xa4, 0x70, 0x94, 0x57, 0x2e, 0x8a, 0x57, 0xc7, 0x53,
0xdd, 0xf4, 0xea, 0x12, 0xd5, 0x83, 0xf4, 0xea, 0x92, 0xd9, 0xb1, 0x36, 0xf5, 0xc5, 0xa5, 0x5f,
0xfd, 0x66, 0xbd, 0xf4, 0x9f, 0xbf, 0x59, 0x9f, 0xfa, 0xf3, 0x97, 0xeb, 0xa5, 0x5f, 0xbd, 0x5c,
0x2f, 0xfd, 0xdb, 0xcb, 0xf5, 0xd2, 0x7f, 0xbf, 0x5c, 0x2f, 0xfd, 0xe2, 0x7f, 0xd6, 0xa7, 0x8e,
0x66, 0xd9, 0x9f, 0x54, 0xdf, 0xff, 0x6d, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfc, 0xa9, 0xc0, 0x61,
0x58, 0x3c, 0x00, 0x00,
}

View file

@ -523,7 +523,6 @@ message LinuxContainerSecurityContext {
repeated int64 supplemental_groups = 8;
// AppArmor profile for the container, candidate values are:
// * runtime/default: equivalent to not specifying a profile.
// * unconfined: no profiles are loaded
// * localhost/<profile_name>: profile loaded on the node
// (localhost) by name. The possible profile names are detailed at
// http://wiki.apparmor.net/index.php/AppArmor_Core_Policy_Reference
@ -828,17 +827,7 @@ message ExecRequest {
// Whether to exec the command in a TTY.
bool tty = 3;
// Whether to stream stdin.
// One of `stdin`, `stdout`, and `stderr` MUST be true.
bool stdin = 4;
// Whether to stream stdout.
// One of `stdin`, `stdout`, and `stderr` MUST be true.
bool stdout = 5;
// Whether to stream stderr.
// One of `stdin`, `stdout`, and `stderr` MUST be true.
// If `tty` is true, `stderr` MUST be false. Multiplexing is not supported
// in this case. The output of stdout and stderr will be combined to a
// single stream.
bool stderr = 6;
}
message ExecResponse {
@ -850,20 +839,10 @@ message AttachRequest {
// ID of the container to which to attach.
string container_id = 1;
// Whether to stream stdin.
// One of `stdin`, `stdout`, and `stderr` MUST be true.
bool stdin = 2;
// Whether the process being attached is running in a TTY.
// This must match the TTY setting in the ContainerConfig.
bool tty = 3;
// Whether to stream stdout.
// One of `stdin`, `stdout`, and `stderr` MUST be true.
bool stdout = 4;
// Whether to stream stderr.
// One of `stdin`, `stdout`, and `stderr` MUST be true.
// If `tty` is true, `stderr` MUST be false. Multiplexing is not supported
// in this case. The output of stdout and stderr will be combined to a
// single stream.
bool stderr = 5;
}
message AttachResponse {

View file

@ -21,7 +21,6 @@ go_library(
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/kubelet/container",
visibility = ["//visibility:public"],
deps = [
"//pkg/api:go_default_library",
@ -58,7 +57,6 @@ go_test(
"ref_test.go",
"sync_result_test.go",
],
importpath = "k8s.io/kubernetes/pkg/kubelet/container",
library = ":go_default_library",
deps = [
"//pkg/api:go_default_library",
@ -73,7 +71,6 @@ go_test(
go_test(
name = "go_default_xtest",
srcs = ["runtime_cache_test.go"],
importpath = "k8s.io/kubernetes/pkg/kubelet/container_test",
deps = [
":go_default_library",
"//pkg/kubelet/container/testing:go_default_library",

View file

@ -127,8 +127,9 @@ type Runtime interface {
// DirectStreamingRuntime is the interface implemented by runtimes for which the streaming calls
// (exec/attach/port-forward) should be served directly by the Kubelet.
type DirectStreamingRuntime interface {
// Runs the command in the container of the specified pod. Attaches
// the processes stdin, stdout, and stderr. Optionally uses a tty.
// Runs the command in the container of the specified pod using nsenter.
// Attaches the processes stdin, stdout, and stderr. Optionally uses a
// tty.
ExecInContainer(containerID ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error
// Forward the specified port from the specified pod to the stream.
PortForward(pod *Pod, port int32, stream io.ReadWriteCloser) error

View file

@ -54,9 +54,9 @@ import (
corelisters "k8s.io/client-go/listers/core/v1"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/record"
"k8s.io/client-go/util/certificate"
"k8s.io/client-go/util/flowcontrol"
"k8s.io/client-go/util/integer"
"k8s.io/kubernetes/cmd/kubelet/app/options"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/cloudprovider"
"k8s.io/kubernetes/pkg/features"
@ -64,7 +64,7 @@ import (
kubeletconfiginternal "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
kubeletconfigv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
"k8s.io/kubernetes/pkg/kubelet/cadvisor"
kubeletcertificate "k8s.io/kubernetes/pkg/kubelet/certificate"
"k8s.io/kubernetes/pkg/kubelet/certificate"
"k8s.io/kubernetes/pkg/kubelet/cm"
"k8s.io/kubernetes/pkg/kubelet/config"
"k8s.io/kubernetes/pkg/kubelet/configmap"
@ -196,28 +196,13 @@ type Bootstrap interface {
// Builder creates and initializes a Kubelet instance
type Builder func(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
kubeDeps *Dependencies,
crOptions *config.ContainerRuntimeOptions,
hostnameOverride string,
nodeIP string,
providerID string,
cloudProvider string,
certDirectory string,
rootDirectory string,
allowedUnsafeSysctls []string,
containerized bool,
remoteRuntimeEndpoint string,
remoteImageEndpoint string,
experimentalMounterPath string,
experimentalKernelMemcgNotification bool,
experimentalCheckNodeCapabilitiesBeforeMount bool,
experimentalNodeAllocatableIgnoreEvictionThreshold bool,
minimumGCAge metav1.Duration,
maxPerPodContainerCount int32,
maxContainerCount int32,
masterServiceNamespace string,
registerSchedulable bool,
nonMasqueradeCIDR string,
keepTerminatedPodVolumes bool) (Bootstrap, error)
crOptions *options.ContainerRuntimeOptions,
hostnameOverride,
nodeIP,
providerID,
cloudProvider,
certDirectory,
rootDirectory string) (Bootstrap, error)
// Dependencies is a bin for things we might consider "injected dependencies" -- objects constructed
// at runtime that are necessary for running the Kubelet. This is a temporary solution for grouping
@ -301,12 +286,12 @@ func makePodSourceConfig(kubeCfg *kubeletconfiginternal.KubeletConfiguration, ku
return cfg, nil
}
func getRuntimeAndImageServices(remoteRuntimeEndpoint string, remoteImageEndpoint string, runtimeRequestTimeout metav1.Duration) (internalapi.RuntimeService, internalapi.ImageManagerService, error) {
rs, err := remote.NewRemoteRuntimeService(remoteRuntimeEndpoint, runtimeRequestTimeout.Duration)
func getRuntimeAndImageServices(config *kubeletconfiginternal.KubeletConfiguration) (internalapi.RuntimeService, internalapi.ImageManagerService, error) {
rs, err := remote.NewRemoteRuntimeService(config.RemoteRuntimeEndpoint, config.RuntimeRequestTimeout.Duration)
if err != nil {
return nil, nil, err
}
is, err := remote.NewRemoteImageService(remoteImageEndpoint, runtimeRequestTimeout.Duration)
is, err := remote.NewRemoteImageService(config.RemoteImageEndpoint, config.RuntimeRequestTimeout.Duration)
if err != nil {
return nil, nil, err
}
@ -317,28 +302,13 @@ func getRuntimeAndImageServices(remoteRuntimeEndpoint string, remoteImageEndpoin
// No initialization of Kubelet and its modules should happen here.
func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
kubeDeps *Dependencies,
crOptions *config.ContainerRuntimeOptions,
hostnameOverride string,
nodeIP string,
providerID string,
cloudProvider string,
certDirectory string,
rootDirectory string,
allowedUnsafeSysctls []string,
containerized bool,
remoteRuntimeEndpoint string,
remoteImageEndpoint string,
experimentalMounterPath string,
experimentalKernelMemcgNotification bool,
experimentalCheckNodeCapabilitiesBeforeMount bool,
experimentalNodeAllocatableIgnoreEvictionThreshold bool,
minimumGCAge metav1.Duration,
maxPerPodContainerCount int32,
maxContainerCount int32,
masterServiceNamespace string,
registerSchedulable bool,
nonMasqueradeCIDR string,
keepTerminatedPodVolumes bool) (*Kubelet, error) {
crOptions *options.ContainerRuntimeOptions,
hostnameOverride,
nodeIP,
providerID,
cloudProvider,
certDirectory,
rootDirectory string) (*Kubelet, error) {
if rootDirectory == "" {
return nil, fmt.Errorf("invalid root directory %q", rootDirectory)
}
@ -406,9 +376,9 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
}
containerGCPolicy := kubecontainer.ContainerGCPolicy{
MinAge: minimumGCAge.Duration,
MaxPerPodContainer: int(maxPerPodContainerCount),
MaxContainers: int(maxContainerCount),
MinAge: kubeCfg.MinimumGCAge.Duration,
MaxPerPodContainer: int(kubeCfg.MaxPerPodContainerCount),
MaxContainers: int(kubeCfg.MaxContainerCount),
}
daemonEndpoints := &v1.NodeDaemonEndpoints{
@ -422,7 +392,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
}
enforceNodeAllocatable := kubeCfg.EnforceNodeAllocatable
if experimentalNodeAllocatableIgnoreEvictionThreshold {
if kubeCfg.ExperimentalNodeAllocatableIgnoreEvictionThreshold {
// Do not provide kubeCfg.EnforceNodeAllocatable to eviction threshold parsing if we are not enforcing Evictions
enforceNodeAllocatable = []string{}
}
@ -434,7 +404,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
PressureTransitionPeriod: kubeCfg.EvictionPressureTransitionPeriod.Duration,
MaxPodGracePeriodSeconds: int64(kubeCfg.EvictionMaxPodGracePeriod),
Thresholds: thresholds,
KernelMemcgNotification: experimentalKernelMemcgNotification,
KernelMemcgNotification: kubeCfg.ExperimentalKernelMemcgNotification,
}
serviceIndexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
@ -488,12 +458,12 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
resyncInterval: kubeCfg.SyncFrequency.Duration,
sourcesReady: config.NewSourcesReady(kubeDeps.PodConfig.SeenAllSources),
registerNode: kubeCfg.RegisterNode,
registerSchedulable: registerSchedulable,
registerSchedulable: kubeCfg.RegisterSchedulable,
clusterDomain: kubeCfg.ClusterDomain,
clusterDNS: clusterDNS,
serviceLister: serviceLister,
nodeInfo: nodeInfo,
masterServiceNamespace: masterServiceNamespace,
masterServiceNamespace: kubeCfg.MasterServiceNamespace,
streamingConnectionIdleTimeout: kubeCfg.StreamingConnectionIdleTimeout.Duration,
recorder: kubeDeps.Recorder,
cadvisor: kubeDeps.CAdvisorInterface,
@ -524,7 +494,6 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
iptablesMasqueradeBit: int(kubeCfg.IPTablesMasqueradeBit),
iptablesDropBit: int(kubeCfg.IPTablesDropBit),
experimentalHostUserNamespaceDefaulting: utilfeature.DefaultFeatureGate.Enabled(features.ExperimentalHostUserNamespaceDefaultingGate),
keepTerminatedPodVolumes: keepTerminatedPodVolumes,
}
secretManager := secret.NewCachingSecretManager(
@ -547,7 +516,17 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
}
glog.Infof("Hairpin mode set to %q", hairpinMode)
plug, err := network.InitNetworkPlugin(kubeDeps.NetworkPlugins, crOptions.NetworkPluginName, &criNetworkHost{&networkHost{klet}, &network.NoopPortMappingGetter{}}, hairpinMode, nonMasqueradeCIDR, int(crOptions.NetworkPluginMTU))
// TODO(#36485) Remove this workaround once we fix the init-container issue.
// Touch iptables lock file, which will be shared among all processes accessing
// the iptables.
f, err := os.OpenFile(utilipt.LockfilePath16x, os.O_CREATE, 0600)
if err != nil {
glog.Warningf("Failed to open iptables lock file: %v", err)
} else if err = f.Close(); err != nil {
glog.Warningf("Failed to close iptables lock file: %v", err)
}
plug, err := network.InitNetworkPlugin(kubeDeps.NetworkPlugins, crOptions.NetworkPluginName, &criNetworkHost{&networkHost{klet}, &network.NoopPortMappingGetter{}}, hairpinMode, kubeCfg.NonMasqueradeCIDR, int(crOptions.NetworkPluginMTU))
if err != nil {
return nil, err
}
@ -566,10 +545,10 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
// podManager is also responsible for keeping secretManager and configMapManager contents up-to-date.
klet.podManager = kubepod.NewBasicPodManager(kubepod.NewBasicMirrorClient(klet.kubeClient), secretManager, configMapManager)
if remoteRuntimeEndpoint != "" {
// remoteImageEndpoint is same as remoteRuntimeEndpoint if not explicitly specified
if remoteImageEndpoint == "" {
remoteImageEndpoint = remoteRuntimeEndpoint
if kubeCfg.RemoteRuntimeEndpoint != "" {
// kubeCfg.RemoteImageEndpoint is same as kubeCfg.RemoteRuntimeEndpoint if not explicitly specified
if kubeCfg.RemoteImageEndpoint == "" {
kubeCfg.RemoteImageEndpoint = kubeCfg.RemoteRuntimeEndpoint
}
}
@ -580,7 +559,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
}
pluginSettings := dockershim.NetworkPluginSettings{
HairpinMode: hairpinMode,
NonMasqueradeCIDR: nonMasqueradeCIDR,
NonMasqueradeCIDR: kubeCfg.NonMasqueradeCIDR,
PluginName: crOptions.NetworkPluginName,
PluginConfDir: crOptions.CNIConfDir,
PluginBinDir: binDir,
@ -608,8 +587,8 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
// Create and start the CRI shim running as a grpc server.
streamingConfig := getStreamingConfig(kubeCfg, kubeDeps)
ds, err := dockershim.NewDockerService(kubeDeps.DockerClient, crOptions.PodSandboxImage, streamingConfig,
&pluginSettings, kubeCfg.RuntimeCgroups, kubeCfg.CgroupDriver, crOptions.DockershimRootDirectory,
crOptions.DockerDisableSharedPID)
&pluginSettings, kubeCfg.RuntimeCgroups, kubeCfg.CgroupDriver, crOptions.DockerExecHandlerName,
crOptions.DockershimRootDirectory, crOptions.DockerDisableSharedPID)
if err != nil {
return nil, err
}
@ -622,10 +601,10 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
// The unix socket for kubelet <-> dockershim communication.
glog.V(5).Infof("RemoteRuntimeEndpoint: %q, RemoteImageEndpoint: %q",
remoteRuntimeEndpoint,
remoteImageEndpoint)
kubeCfg.RemoteRuntimeEndpoint,
kubeCfg.RemoteImageEndpoint)
glog.V(2).Infof("Starting the GRPC server for the docker CRI shim.")
server := dockerremote.NewDockerServer(remoteRuntimeEndpoint, ds)
server := dockerremote.NewDockerServer(kubeCfg.RemoteRuntimeEndpoint, ds)
if err := server.Start(); err != nil {
return nil, err
}
@ -644,7 +623,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
default:
return nil, fmt.Errorf("unsupported CRI runtime: %q", kubeCfg.ContainerRuntime)
}
runtimeService, imageService, err := getRuntimeAndImageServices(remoteRuntimeEndpoint, remoteImageEndpoint, kubeCfg.RuntimeRequestTimeout)
runtimeService, imageService, err := getRuntimeAndImageServices(kubeCfg)
if err != nil {
return nil, err
}
@ -681,7 +660,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
// be removed. Related issue:
// https://github.com/kubernetes/kubernetes/issues/51798
if (kubeCfg.ContainerRuntime == kubetypes.DockerContainerRuntime &&
goruntime.GOOS == "linux") || remoteRuntimeEndpoint == "/var/run/crio.sock" {
goruntime.GOOS == "linux") || kubeCfg.RemoteRuntimeEndpoint == "/var/run/crio.sock" {
klet.StatsProvider = stats.NewCadvisorStatsProvider(
klet.cadvisor,
klet.resourceAnalyzer,
@ -774,7 +753,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
ips = append(ips, cloudIPs...)
names := append([]string{klet.GetHostname(), hostnameOverride}, cloudNames...)
klet.serverCertificateManager, err = kubeletcertificate.NewKubeletServerCertificateManager(klet.kubeClient, kubeCfg, klet.nodeName, ips, names, certDirectory)
klet.serverCertificateManager, err = certificate.NewKubeletServerCertificateManager(klet.kubeClient, kubeCfg, klet.nodeName, ips, names, certDirectory)
if err != nil {
return nil, fmt.Errorf("failed to initialize certificate manager: %v", err)
}
@ -802,11 +781,11 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
// If the experimentalMounterPathFlag is set, we do not want to
// check node capabilities since the mount path is not the default
if len(experimentalMounterPath) != 0 {
experimentalCheckNodeCapabilitiesBeforeMount = false
if len(kubeCfg.ExperimentalMounterPath) != 0 {
kubeCfg.ExperimentalCheckNodeCapabilitiesBeforeMount = false
// Replace the nameserver in containerized-mounter's rootfs/etc/resolve.conf with kubelet.ClusterDNS
// so that service name could be resolved
klet.setupDNSinContainerizedMounter(experimentalMounterPath)
klet.setupDNSinContainerizedMounter(kubeCfg.ExperimentalMounterPath)
}
// setup volumeManager
@ -821,8 +800,8 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
kubeDeps.Mounter,
klet.getPodsDir(),
kubeDeps.Recorder,
experimentalCheckNodeCapabilitiesBeforeMount,
keepTerminatedPodVolumes)
kubeCfg.ExperimentalCheckNodeCapabilitiesBeforeMount,
kubeCfg.KeepTerminatedPodVolumes)
runtimeCache, err := kubecontainer.NewRuntimeCache(klet.containerRuntime)
if err != nil {
@ -854,7 +833,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
}
// Safe, whitelisted sysctls can always be used as unsafe sysctls in the spec
// Hence, we concatenate those two lists.
safeAndUnsafeSysctls := append(sysctl.SafeSysctlWhitelist(), allowedUnsafeSysctls...)
safeAndUnsafeSysctls := append(sysctl.SafeSysctlWhitelist(), kubeCfg.AllowedUnsafeSysctls...)
unsafeWhitelist, err := sysctl.NewWhitelist(safeAndUnsafeSysctls, v1.UnsafeSysctlsPodAnnotationKey)
if err != nil {
return nil, err
@ -1179,13 +1158,6 @@ type Kubelet struct {
// StatsProvider provides the node and the container stats.
*stats.StatsProvider
// containerized should be set to true if the kubelet is running in a container
containerized bool
// This flag, if set, instructs the kubelet to keep volumes from terminated pods mounted to the node.
// This can be useful for debugging volume related issues.
keepTerminatedPodVolumes bool // DEPRECATED
}
func allLocalIPsWithoutLoopback() ([]net.IP, error) {
@ -1473,10 +1445,6 @@ func (kl *Kubelet) GetClusterDNS(pod *v1.Pod) ([]string, []string, bool, error)
//
// If any step of this workflow errors, the error is returned, and is repeated
// on the next syncPod call.
//
// This operation writes all events that are dispatched in order to provide
// the most accurate information possible about an error situation to aid debugging.
// Callers should not throw an event if this operation returns an error.
func (kl *Kubelet) syncPod(o syncPodOptions) error {
// pull out the required options
pod := o.pod
@ -1494,7 +1462,6 @@ func (kl *Kubelet) syncPod(o syncPodOptions) error {
kl.statusManager.SetPodStatus(pod, apiPodStatus)
// we kill the pod with the specified grace period since this is a termination
if err := kl.killPod(pod, nil, podStatus, killPodOptions.PodTerminationGracePeriodSecondsOverride); err != nil {
kl.recorder.Eventf(pod, v1.EventTypeWarning, events.FailedToKillPod, "error killing pod: %v", err)
// there was an error killing the pod, so we return that error directly
utilruntime.HandleError(err)
return err
@ -1561,7 +1528,6 @@ func (kl *Kubelet) syncPod(o syncPodOptions) error {
if !runnable.Admit || pod.DeletionTimestamp != nil || apiPodStatus.Phase == v1.PodFailed {
var syncErr error
if err := kl.killPod(pod, nil, podStatus, nil); err != nil {
kl.recorder.Eventf(pod, v1.EventTypeWarning, events.FailedToKillPod, "error killing pod: %v", err)
syncErr = fmt.Errorf("error killing pod: %v", err)
utilruntime.HandleError(syncErr)
} else {
@ -1576,7 +1542,6 @@ func (kl *Kubelet) syncPod(o syncPodOptions) error {
// If the network plugin is not ready, only start the pod if it uses the host network
if rs := kl.runtimeState.networkErrors(); len(rs) != 0 && !kubecontainer.IsHostNetworkPod(pod) {
kl.recorder.Eventf(pod, v1.EventTypeWarning, events.NetworkNotReady, "network is not ready: %v", rs)
return fmt.Errorf("network is not ready: %v", rs)
}
@ -1619,7 +1584,6 @@ func (kl *Kubelet) syncPod(o syncPodOptions) error {
glog.V(2).Infof("Failed to update QoS cgroups while syncing pod: %v", err)
}
if err := pcm.EnsureExists(pod); err != nil {
kl.recorder.Eventf(pod, v1.EventTypeWarning, events.FailedToCreatePodContainer, "unable to ensure pod container exists: %v", err)
return fmt.Errorf("failed to ensure that the pod: %v cgroups exist and are correctly applied: %v", pod.UID, err)
}
}
@ -1643,21 +1607,15 @@ func (kl *Kubelet) syncPod(o syncPodOptions) error {
}
}
if mirrorPod == nil || deleted {
node, err := kl.GetNode()
if err != nil || node.DeletionTimestamp != nil {
glog.V(4).Infof("No need to create a mirror pod, since node %q has been removed from the cluster", kl.nodeName)
} else {
glog.V(4).Infof("Creating a mirror pod for static pod %q", format.Pod(pod))
if err := kl.podManager.CreateMirrorPod(pod); err != nil {
glog.Errorf("Failed creating a mirror pod for %q: %v", format.Pod(pod), err)
}
glog.V(3).Infof("Creating a mirror pod for static pod %q", format.Pod(pod))
if err := kl.podManager.CreateMirrorPod(pod); err != nil {
glog.Errorf("Failed creating a mirror pod for %q: %v", format.Pod(pod), err)
}
}
}
// Make data directories for the pod
if err := kl.makePodDataDirs(pod); err != nil {
kl.recorder.Eventf(pod, v1.EventTypeWarning, events.FailedToMakePodDataDirectories, "error making pod data directories: %v", err)
glog.Errorf("Unable to make pod data directories for pod %q: %v", format.Pod(pod), err)
return err
}
@ -1679,8 +1637,6 @@ func (kl *Kubelet) syncPod(o syncPodOptions) error {
result := kl.containerRuntime.SyncPod(pod, apiPodStatus, podStatus, pullSecrets, kl.backOff)
kl.reasonCache.Update(pod.UID, result)
if err := result.Error(); err != nil {
// Do not record an event here, as we keep all event logging for sync pod failures
// local to container runtime so we get better errors
return err
}
@ -1932,7 +1888,7 @@ func (kl *Kubelet) syncLoopIteration(configCh <-chan kubetypes.PodUpdate, handle
break
}
glog.V(4).Infof("SyncLoop (SYNC): %d pods; %s", len(podsToSync), format.Pods(podsToSync))
handler.HandlePodSyncs(podsToSync)
kl.HandlePodSyncs(podsToSync)
case update := <-kl.livenessManager.Updates():
if update.Result == proberesults.Failure {
// The liveness manager detected a failure; sync the pod.

View file

@ -27,8 +27,8 @@ import (
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/kubernetes/cmd/kubelet/app/options"
"k8s.io/kubernetes/pkg/kubelet/cm"
"k8s.io/kubernetes/pkg/kubelet/config"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
utilfile "k8s.io/kubernetes/pkg/util/file"
utilnode "k8s.io/kubernetes/pkg/util/node"
@ -46,7 +46,7 @@ func (kl *Kubelet) getRootDir() string {
// getPodsDir returns the full path to the directory under which pod
// directories are created.
func (kl *Kubelet) getPodsDir() string {
return filepath.Join(kl.getRootDir(), config.DefaultKubeletPodsDirName)
return filepath.Join(kl.getRootDir(), options.DefaultKubeletPodsDirName)
}
// getPluginsDir returns the full path to the directory under which plugin
@ -54,7 +54,7 @@ func (kl *Kubelet) getPodsDir() string {
// they need to persist. Plugins should create subdirectories under this named
// after their own names.
func (kl *Kubelet) getPluginsDir() string {
return filepath.Join(kl.getRootDir(), config.DefaultKubeletPluginsDirName)
return filepath.Join(kl.getRootDir(), options.DefaultKubeletPluginsDirName)
}
// getPluginDir returns a data directory name for a given plugin name.
@ -80,7 +80,7 @@ func (kl *Kubelet) getPodDir(podUID types.UID) string {
// which volumes are created for the specified pod. This directory may not
// exist if the pod does not exist.
func (kl *Kubelet) getPodVolumesDir(podUID types.UID) string {
return filepath.Join(kl.getPodDir(podUID), config.DefaultKubeletVolumesDirName)
return filepath.Join(kl.getPodDir(podUID), options.DefaultKubeletVolumesDirName)
}
// getPodVolumeDir returns the full path to the directory which represents the
@ -94,7 +94,7 @@ func (kl *Kubelet) getPodVolumeDir(podUID types.UID, pluginName string, volumeNa
// which plugins may store data for the specified pod. This directory may not
// exist if the pod does not exist.
func (kl *Kubelet) getPodPluginsDir(podUID types.UID) string {
return filepath.Join(kl.getPodDir(podUID), config.DefaultKubeletPluginsDirName)
return filepath.Join(kl.getPodDir(podUID), options.DefaultKubeletPluginsDirName)
}
// getPodPluginDir returns a data directory name for a given plugin name for a
@ -108,7 +108,7 @@ func (kl *Kubelet) getPodPluginDir(podUID types.UID, pluginName string) string {
// which container data is held for the specified pod. This directory may not
// exist if the pod or container does not exist.
func (kl *Kubelet) getPodContainerDir(podUID types.UID, ctrName string) string {
return filepath.Join(kl.getPodDir(podUID), config.DefaultKubeletContainersDirName, ctrName)
return filepath.Join(kl.getPodDir(podUID), options.DefaultKubeletContainersDirName, ctrName)
}
// GetPods returns all pods bound to the kubelet and their spec, and the mirror

View file

@ -30,6 +30,7 @@ import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/types"
utilnet "k8s.io/apimachinery/pkg/util/net"
utilfeature "k8s.io/apiserver/pkg/util/feature"
@ -117,9 +118,15 @@ func (kl *Kubelet) tryRegisterWithAPIServer(node *v1.Node) bool {
return false
}
originalNode := existingNode.DeepCopy()
if originalNode == nil {
glog.Errorf("Nil %q node object", kl.nodeName)
clonedNode, err := conversion.NewCloner().DeepCopy(existingNode)
if err != nil {
glog.Errorf("Unable to clone %q node object %#v: %v", kl.nodeName, existingNode, err)
return false
}
originalNode, ok := clonedNode.(*v1.Node)
if !ok || originalNode == nil {
glog.Errorf("Unable to cast %q node object %#v to v1.Node", kl.nodeName, clonedNode)
return false
}
@ -169,6 +176,10 @@ func (kl *Kubelet) updateDefaultLabels(initialNode, existingNode *v1.Node) bool
var needsUpdate bool = false
//Set default labels but make sure to not set labels with empty values
for _, label := range defaultLabels {
if _, hasInitialValue := initialNode.Labels[label]; !hasInitialValue {
continue
}
if existingNode.Labels[label] != initialNode.Labels[label] {
existingNode.Labels[label] = initialNode.Labels[label]
needsUpdate = true
@ -272,7 +283,7 @@ func (kl *Kubelet) initialNode() (*v1.Node, error) {
glog.Infof("Controller attach/detach is disabled for this node; Kubelet will attach and detach volumes")
}
if kl.keepTerminatedPodVolumes {
if kl.kubeletConfiguration.KeepTerminatedPodVolumes {
if node.Annotations == nil {
node.Annotations = make(map[string]string)
}
@ -402,9 +413,14 @@ func (kl *Kubelet) tryUpdateNodeStatus(tryNumber int) error {
return fmt.Errorf("error getting node %q: %v", kl.nodeName, err)
}
originalNode := node.DeepCopy()
if originalNode == nil {
return fmt.Errorf("nil %q node object", kl.nodeName)
clonedNode, err := conversion.NewCloner().DeepCopy(node)
if err != nil {
return fmt.Errorf("error clone node %q: %v", kl.nodeName, err)
}
originalNode, ok := clonedNode.(*v1.Node)
if !ok || originalNode == nil {
return fmt.Errorf("failed to cast %q node object %#v to v1.Node", kl.nodeName, clonedNode)
}
kl.updatePodCIDR(node.Spec.PodCIDR)
@ -440,9 +456,6 @@ func (kl *Kubelet) setNodeAddress(node *v1.Node) error {
}
if kl.externalCloudProvider {
if kl.nodeIP != nil {
node.ObjectMeta.Annotations[kubeletapis.AnnotationProvidedIPAddr] = kl.nodeIP.String()
}
// We rely on the external cloud provider to supply the addresses.
return nil
}
@ -500,6 +513,7 @@ func (kl *Kubelet) setNodeAddress(node *v1.Node) error {
// 4) Try to get the IP from the network interface used as default gateway
if kl.nodeIP != nil {
ipAddr = kl.nodeIP
node.ObjectMeta.Annotations[kubeletapis.AnnotationProvidedIPAddr] = kl.nodeIP.String()
} else if addr := net.ParseIP(kl.hostname); addr != nil {
ipAddr = addr
} else {

View file

@ -1233,6 +1233,37 @@ func TestUpdateDefaultLabels(t *testing.T) {
"please-persist": "foo",
},
},
{
name: "make sure existing labels do not get deleted when initial node has no opinion",
initialNode: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{},
},
},
existingNode: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
kubeletapis.LabelHostname: "new-hostname",
kubeletapis.LabelZoneFailureDomain: "new-zone-failure-domain",
kubeletapis.LabelZoneRegion: "new-zone-region",
kubeletapis.LabelInstanceType: "new-instance-type",
kubeletapis.LabelOS: "new-os",
kubeletapis.LabelArch: "new-arch",
"please-persist": "foo",
},
},
},
needsUpdate: false,
finalLabels: map[string]string{
kubeletapis.LabelHostname: "new-hostname",
kubeletapis.LabelZoneFailureDomain: "new-zone-failure-domain",
kubeletapis.LabelZoneRegion: "new-zone-region",
kubeletapis.LabelInstanceType: "new-instance-type",
kubeletapis.LabelOS: "new-os",
kubeletapis.LabelArch: "new-arch",
"please-persist": "foo",
},
},
{
name: "no update needed",
initialNode: &v1.Node{

View file

@ -127,8 +127,8 @@ func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, h
mountEtcHostsFile = mountEtcHostsFile && (mount.MountPath != etcHostsPath)
vol, ok := podVolumes[mount.Name]
if !ok || vol.Mounter == nil {
glog.Errorf("Mount cannot be satisfied for container %q, because the volume is missing or the volume mounter is nil: %+v", container.Name, mount)
return nil, fmt.Errorf("cannot find volume %q to mount into container %q", mount.Name, container.Name)
glog.Warningf("Mount cannot be satisfied for container %q, because the volume is missing or the volume mounter is nil: %q", container.Name, mount)
continue
}
relabelVolume := false
@ -864,7 +864,7 @@ func (kl *Kubelet) PodResourcesAreReclaimed(pod *v1.Pod, status v1.PodStatus) bo
glog.V(3).Infof("Pod %q is terminated, but some containers have not been cleaned up: %+v", format.Pod(pod), runtimeStatus.ContainerStatuses)
return false
}
if kl.podVolumesExist(pod.UID) && !kl.keepTerminatedPodVolumes {
if kl.podVolumesExist(pod.UID) && !kl.kubeletConfiguration.KeepTerminatedPodVolumes {
// We shouldnt delete pods whose volumes have not been cleaned up if we are not keeping terminated pod volumes
glog.V(3).Infof("Pod %q is terminated, but some volumes have not been cleaned up", format.Pod(pod))
return false
@ -1348,16 +1348,21 @@ func (kl *Kubelet) convertStatusToAPIStatus(pod *v1.Pod, podStatus *kubecontaine
// set status for Pods created on versions of kube older than 1.6
apiPodStatus.QOSClass = v1qos.GetPodQOS(pod)
oldPodStatus, found := kl.statusManager.GetPodStatus(pod.UID)
if !found {
oldPodStatus = pod.Status
}
apiPodStatus.ContainerStatuses = kl.convertToAPIContainerStatuses(
pod, podStatus,
pod.Status.ContainerStatuses,
oldPodStatus.ContainerStatuses,
pod.Spec.Containers,
len(pod.Spec.InitContainers) > 0,
false,
)
apiPodStatus.InitContainerStatuses = kl.convertToAPIContainerStatuses(
pod, podStatus,
pod.Status.InitContainerStatuses,
oldPodStatus.InitContainerStatuses,
pod.Spec.InitContainers,
len(pod.Spec.InitContainers) > 0,
true,
@ -1424,7 +1429,7 @@ func (kl *Kubelet) convertToAPIContainerStatuses(pod *v1.Pod, podStatus *kubecon
}
oldStatus, found := oldStatuses[container.Name]
if found {
if isInitContainer && oldStatus.State.Terminated != nil {
if oldStatus.State.Terminated != nil {
// Do not update status on terminated init containers as
// they be removed at any time.
status = &oldStatus
@ -1704,7 +1709,7 @@ func (kl *Kubelet) cleanupOrphanedPodCgroups(cgroupPods map[types.UID]cm.CgroupN
// parent croup. If the volumes still exist, reduce the cpu shares for any
// process in the cgroup to the minimum value while we wait. if the kubelet
// is configured to keep terminated volumes, we will delete the cgroup and not block.
if podVolumesExist := kl.podVolumesExist(uid); podVolumesExist && !kl.keepTerminatedPodVolumes {
if podVolumesExist := kl.podVolumesExist(uid); podVolumesExist && !kl.kubeletConfiguration.KeepTerminatedPodVolumes {
glog.V(3).Infof("Orphaned pod %q found, but volumes not yet removed. Reducing cpu to minimum", uid)
if err := pcm.ReduceCPULimits(val); err != nil {
glog.Warningf("Failed to reduce cpu time for pod %q pending volume cleanup due to %v", uid, err)

View file

@ -223,36 +223,6 @@ func TestMakeMounts(t *testing.T) {
expectErr: true,
expectedErrMsg: "unable to provision SubPath `no/backsteps/../allowed`: must not contain '..'",
},
"volume doesn't exist": {
podVolumes: kubecontainer.VolumeMap{},
container: v1.Container{
VolumeMounts: []v1.VolumeMount{
{
MountPath: "/mnt/path3",
Name: "disk",
ReadOnly: true,
},
},
},
expectErr: true,
expectedErrMsg: "cannot find volume \"disk\" to mount into container \"\"",
},
"volume mounter is nil": {
podVolumes: kubecontainer.VolumeMap{
"disk": kubecontainer.VolumeInfo{},
},
container: v1.Container{
VolumeMounts: []v1.VolumeMount{
{
MountPath: "/mnt/path3",
Name: "disk",
ReadOnly: true,
},
},
},
expectErr: true,
expectedErrMsg: "cannot find volume \"disk\" to mount into container \"\"",
},
}
for name, tc := range testCases {

View file

@ -22,6 +22,7 @@ import (
"github.com/golang/glog"
"k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/kubernetes/pkg/api/v1/resource"
)
@ -43,14 +44,28 @@ func (kl *Kubelet) defaultPodLimitsForDownwardAPI(pod *v1.Pod, container *v1.Con
}
allocatable := node.Status.Allocatable
glog.Infof("allocatable: %v", allocatable)
outputPod := pod.DeepCopy()
podCopy, err := scheme.Scheme.Copy(pod)
if err != nil {
return nil, nil, fmt.Errorf("failed to perform a deep copy of pod object: %v", err)
}
outputPod, ok := podCopy.(*v1.Pod)
if !ok {
return nil, nil, fmt.Errorf("unexpected type returned from deep copy of pod object")
}
for idx := range outputPod.Spec.Containers {
resource.MergeContainerResourceLimits(&outputPod.Spec.Containers[idx], allocatable)
}
var outputContainer *v1.Container
if container != nil {
outputContainer = container.DeepCopy()
containerCopy, err := scheme.Scheme.DeepCopy(container)
if err != nil {
return nil, nil, fmt.Errorf("failed to perform a deep copy of container object: %v", err)
}
outputContainer, ok = containerCopy.(*v1.Container)
if !ok {
return nil, nil, fmt.Errorf("unexpected type returned from deep copy of container object")
}
resource.MergeContainerResourceLimits(outputContainer, allocatable)
}
return outputPod, outputContainer, nil

View file

@ -69,6 +69,7 @@ func (kl *Kubelet) newVolumeMounterFromPlugins(spec *volume.Spec, pod *v1.Pod, o
if err != nil {
return nil, fmt.Errorf("can't use volume plugins for %s: %v", spec.Name(), err)
}
opts.Containerized = kl.kubeletConfiguration.Containerized
physicalMounter, err := plugin.NewMounter(spec, pod, opts)
if err != nil {
return nil, fmt.Errorf("failed to instantiate mounter for volume: %s using plugin: %s with a root cause: %v", spec.Name(), plugin.GetPluginName(), err)

View file

@ -58,7 +58,9 @@ func TestListVolumesForPod(t *testing.T) {
})
stopCh := runVolumeManager(kubelet)
defer close(stopCh)
defer func() {
close(stopCh)
}()
kubelet.podManager.SetPods([]*v1.Pod{pod})
err := kubelet.volumeManager.WaitForAttachAndMount(pod)
@ -140,7 +142,9 @@ func TestPodVolumesExist(t *testing.T) {
}
stopCh := runVolumeManager(kubelet)
defer close(stopCh)
defer func() {
close(stopCh)
}()
kubelet.podManager.SetPods(pods)
for _, pod := range pods {
@ -173,7 +177,9 @@ func TestVolumeAttachAndMountControllerDisabled(t *testing.T) {
})
stopCh := runVolumeManager(kubelet)
defer close(stopCh)
defer func() {
close(stopCh)
}()
kubelet.podManager.SetPods([]*v1.Pod{pod})
err := kubelet.volumeManager.WaitForAttachAndMount(pod)
@ -217,7 +223,9 @@ func TestVolumeUnmountAndDetachControllerDisabled(t *testing.T) {
})
stopCh := runVolumeManager(kubelet)
defer close(stopCh)
defer func() {
close(stopCh)
}()
// Add pod
kubelet.podManager.SetPods([]*v1.Pod{pod})
@ -304,7 +312,9 @@ func TestVolumeAttachAndMountControllerEnabled(t *testing.T) {
})
stopCh := runVolumeManager(kubelet)
defer close(stopCh)
defer func() {
close(stopCh)
}()
kubelet.podManager.SetPods([]*v1.Pod{pod})
@ -371,7 +381,9 @@ func TestVolumeUnmountAndDetachControllerEnabled(t *testing.T) {
})
stopCh := runVolumeManager(kubelet)
defer close(stopCh)
defer func() {
close(stopCh)
}()
// Add pod
kubelet.podManager.SetPods([]*v1.Pod{pod})

View file

@ -162,9 +162,6 @@ func (p *podWorkers) managePodLoop(podUpdates <-chan UpdatePodOptions) {
// the previous sync.
status, err := p.podCache.GetNewerThan(podUID, lastSyncTime)
if err != nil {
// This is the legacy event thrown by manage pod loop
// all other events are now dispatched from syncPodFn
p.recorder.Eventf(update.Pod, v1.EventTypeWarning, events.FailedSync, "error determining status: %v", err)
return err
}
err = p.syncPodFn(syncPodOptions{
@ -182,8 +179,14 @@ func (p *podWorkers) managePodLoop(podUpdates <-chan UpdatePodOptions) {
update.OnCompleteFunc(err)
}
if err != nil {
// IMPORTANT: we do not log errors here, the syncPodFn is responsible for logging errors
glog.Errorf("Error syncing pod %s (%q), skipping: %v", update.Pod.UID, format.Pod(update.Pod), err)
// if we failed sync, we throw more specific events for why it happened.
// as a result, i question the value of this event.
// TODO: determine if we can remove this in a future release.
// do not include descriptive text that can vary on why it failed so in a pathological
// scenario, kubelet does not create enough discrete events that miss default aggregation
// window.
p.recorder.Eventf(update.Pod, v1.EventTypeWarning, events.FailedSync, "Error syncing pod")
}
p.wrapUp(update.Pod.UID, err)
}

View file

@ -15,7 +15,6 @@ go_library(
"pod_update.go",
"types.go",
],
importpath = "k8s.io/kubernetes/pkg/kubelet/types",
deps = [
"//pkg/api:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
@ -31,7 +30,6 @@ go_test(
"pod_update_test.go",
"types_test.go",
],
importpath = "k8s.io/kubernetes/pkg/kubelet/types",
library = ":go_default_library",
deps = [
"//vendor/github.com/stretchr/testify/assert:go_default_library",

View file

@ -9,7 +9,6 @@ load(
go_test(
name = "go_default_test",
srcs = ["util_test.go"],
importpath = "k8s.io/kubernetes/pkg/kubelet/util",
library = ":go_default_library",
deps = ["//vendor/github.com/stretchr/testify/assert:go_default_library"],
)
@ -29,7 +28,6 @@ go_library(
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/kubelet/util",
deps = [
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
] + select({

View file

@ -12,7 +12,6 @@ go_library(
"pod.go",
"resources.go",
],
importpath = "k8s.io/kubernetes/pkg/kubelet/util/format",
deps = [
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
@ -22,7 +21,6 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["resources_test.go"],
importpath = "k8s.io/kubernetes/pkg/kubelet/util/format",
library = ":go_default_library",
deps = [
"//vendor/k8s.io/api/core/v1:go_default_library",

View file

@ -8,7 +8,6 @@ load(
go_library(
name = "go_default_library",
srcs = ["ioutils.go"],
importpath = "k8s.io/kubernetes/pkg/kubelet/util/ioutils",
)
filegroup(

View file

@ -9,7 +9,6 @@ load(
go_library(
name = "go_default_library",
srcs = ["sliceutils.go"],
importpath = "k8s.io/kubernetes/pkg/kubelet/util/sliceutils",
deps = [
"//pkg/kubelet/container:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
@ -32,7 +31,6 @@ filegroup(
go_test(
name = "go_default_test",
srcs = ["sliceutils_test.go"],
importpath = "k8s.io/kubernetes/pkg/kubelet/util/sliceutils",
library = ":go_default_library",
deps = [
"//pkg/kubelet/container:go_default_library",

View file

@ -8,7 +8,6 @@ load(
go_library(
name = "go_default_library",
srcs = ["doc.go"],
importpath = "k8s.io/kubernetes/pkg/security",
)
filegroup(

View file

@ -13,7 +13,6 @@ go_library(
"validate.go",
"validate_disabled.go",
],
importpath = "k8s.io/kubernetes/pkg/security/apparmor",
deps = [
"//pkg/features:go_default_library",
"//pkg/kubelet/types:go_default_library",
@ -29,7 +28,6 @@ go_test(
data = [
"testdata/profiles",
],
importpath = "k8s.io/kubernetes/pkg/security/apparmor",
library = ":go_default_library",
deps = [
"//vendor/github.com/stretchr/testify/assert:go_default_library",

View file

@ -35,16 +35,13 @@ const (
ProfileRuntimeDefault = "runtime/default"
// The prefix for specifying profiles loaded on the node.
ProfileNamePrefix = "localhost/"
// Unconfined profile
ProfileNameUnconfined = "unconfined"
)
// Checks whether app armor is required for pod to be run.
func isRequired(pod *v1.Pod) bool {
for key, value := range pod.Annotations {
for key := range pod.Annotations {
if strings.HasPrefix(key, ContainerAnnotationKeyPrefix) {
return value != ProfileNameUnconfined
return true
}
}
return false

View file

@ -136,7 +136,7 @@ func validateProfile(profile string, loadedProfiles map[string]bool) error {
}
func ValidateProfileFormat(profile string) error {
if profile == "" || profile == ProfileRuntimeDefault || profile == ProfileNameUnconfined {
if profile == "" || profile == ProfileRuntimeDefault {
return nil
}
if !strings.HasPrefix(profile, ProfileNamePrefix) {

View file

@ -63,7 +63,6 @@ func TestValidateProfile(t *testing.T) {
}{
{"", true},
{ProfileRuntimeDefault, true},
{ProfileNameUnconfined, true},
{"baz", false}, // Missing local prefix.
{ProfileNamePrefix + "/usr/sbin/ntpd", true},
{ProfileNamePrefix + "foo-bar", true},

View file

@ -12,7 +12,6 @@ go_library(
"jwt.go",
"util.go",
],
importpath = "k8s.io/kubernetes/pkg/serviceaccount",
deps = [
"//pkg/api:go_default_library",
"//vendor/github.com/dgrijalva/jwt-go:go_default_library",
@ -27,7 +26,6 @@ go_library(
go_test(
name = "go_default_xtest",
srcs = ["jwt_test.go"],
importpath = "k8s.io/kubernetes/pkg/serviceaccount_test",
deps = [
":go_default_library",
"//pkg/controller/serviceaccount:go_default_library",

View file

@ -38,7 +38,6 @@ filegroup(
"//pkg/util/net:all-srcs",
"//pkg/util/netsh:all-srcs",
"//pkg/util/node:all-srcs",
"//pkg/util/nsenter:all-srcs",
"//pkg/util/oom:all-srcs",
"//pkg/util/parsers:all-srcs",
"//pkg/util/pointer:all-srcs",

View file

@ -8,7 +8,6 @@ load(
go_library(
name = "go_default_library",
srcs = ["file.go"],
importpath = "k8s.io/kubernetes/pkg/util/file",
)
filegroup(

View file

@ -13,7 +13,6 @@ go_library(
"filesystem.go",
"watcher.go",
],
importpath = "k8s.io/kubernetes/pkg/util/filesystem",
deps = [
"//vendor/github.com/fsnotify/fsnotify:go_default_library",
"//vendor/github.com/spf13/afero:go_default_library",

View file

@ -62,11 +62,6 @@ func (DefaultFs) RemoveAll(path string) error {
return os.RemoveAll(path)
}
// Remove via os.RemoveAll
func (DefaultFs) Remove(name string) error {
return os.Remove(name)
}
// ReadFile via ioutil.ReadFile
func (DefaultFs) ReadFile(filename string) ([]byte, error) {
return ioutil.ReadFile(filename)

View file

@ -92,11 +92,6 @@ func (fs *fakeFs) RemoveAll(path string) error {
return fs.a.RemoveAll(path)
}
// Remove via afero.RemoveAll
func (fs *fakeFs) Remove(name string) error {
return fs.a.Remove(name)
}
// fakeFile implements File; for use with fakeFs
type fakeFile struct {
file afero.File

View file

@ -31,7 +31,6 @@ type Filesystem interface {
MkdirAll(path string, perm os.FileMode) error
Chtimes(name string, atime time.Time, mtime time.Time) error
RemoveAll(path string) error
Remove(name string) error
// from "io/ioutil"
ReadFile(filename string) ([]byte, error)

View file

@ -9,14 +9,12 @@ load(
go_library(
name = "go_default_library",
srcs = ["hash.go"],
importpath = "k8s.io/kubernetes/pkg/util/hash",
deps = ["//vendor/github.com/davecgh/go-spew/spew:go_default_library"],
)
go_test(
name = "go_default_test",
srcs = ["hash_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/hash",
library = ":go_default_library",
deps = ["//vendor/github.com/davecgh/go-spew/spew:go_default_library"],
)

View file

@ -11,7 +11,6 @@ go_library(
"consistentread.go",
"writer.go",
],
importpath = "k8s.io/kubernetes/pkg/util/io",
deps = ["//vendor/github.com/golang/glog:go_default_library"],
)

View file

@ -25,14 +25,12 @@ go_library(
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/util/mount",
deps = [
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"//pkg/util/io:go_default_library",
"//pkg/util/nsenter:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
],
@ -54,7 +52,6 @@ go_test(
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/util/mount",
library = ":go_default_library",
deps = ["//vendor/k8s.io/utils/exec/testing:go_default_library"],
)

View file

@ -125,7 +125,7 @@ func (f *FakeMounter) List() ([]MountPoint, error) {
}
func (f *FakeMounter) IsMountPointMatch(mp MountPoint, dir string) bool {
return mp.Path == dir
return (mp.Path == dir)
}
func (f *FakeMounter) IsNotMountPoint(dir string) (bool, error) {
@ -175,19 +175,3 @@ func (f *FakeMounter) GetDeviceNameFromMount(mountPath, pluginDir string) (strin
func (f *FakeMounter) MakeRShared(path string) error {
return nil
}
func (f *FakeMounter) GetFileType(pathname string) (FileType, error) {
return FileType("fake"), nil
}
func (f *FakeMounter) MakeDir(pathname string) error {
return nil
}
func (f *FakeMounter) MakeFile(pathname string) error {
return nil
}
func (f *FakeMounter) ExistsPath(pathname string) bool {
return false
}

View file

@ -19,25 +19,13 @@ limitations under the License.
package mount
import (
"fmt"
"path"
"path/filepath"
"strings"
"github.com/golang/glog"
)
type FileType string
const (
// Default mount command if mounter path is not specified
defaultMountCommand = "mount"
MountsInGlobalPDPath = "mounts"
FileTypeDirectory FileType = "Directory"
FileTypeFile FileType = "File"
FileTypeSocket FileType = "Socket"
FileTypeCharDev FileType = "CharDevice"
FileTypeBlockDev FileType = "BlockDevice"
defaultMountCommand = "mount"
MountsInGlobalPDPath = "mounts"
)
type Interface interface {
@ -77,18 +65,6 @@ type Interface interface {
// MakeRShared checks that given path is on a mount with 'rshared' mount
// propagation. If not, it bind-mounts the path as rshared.
MakeRShared(path string) error
// GetFileType checks for file/directory/socket/block/character devices.
// Will operate in the host mount namespace if kubelet is running in a container
GetFileType(pathname string) (FileType, error)
// MakeFile creates an empty file.
// Will operate in the host mount namespace if kubelet is running in a container
MakeFile(pathname string) error
// MakeDir creates a new directory.
// Will operate in the host mount namespace if kubelet is running in a container
MakeDir(pathname string) error
// ExistsPath checks whether the path exists.
// Will operate in the host mount namespace if kubelet is running in a container
ExistsPath(pathname string) bool
}
// Exec executes command where mount utilities are. This can be either the host,
@ -138,41 +114,6 @@ func (mounter *SafeFormatAndMount) FormatAndMount(source string, target string,
return mounter.formatAndMount(source, target, fstype, options)
}
// GetMountRefs finds all other references to the device referenced
// by mountPath; returns a list of paths.
func GetMountRefs(mounter Interface, mountPath string) ([]string, error) {
mps, err := mounter.List()
if err != nil {
return nil, err
}
// Find the device name.
deviceName := ""
// If mountPath is symlink, need get its target path.
slTarget, err := filepath.EvalSymlinks(mountPath)
if err != nil {
slTarget = mountPath
}
for i := range mps {
if mps[i].Path == slTarget {
deviceName = mps[i].Device
break
}
}
// Find all references to the device.
var refs []string
if deviceName == "" {
glog.Warningf("could not determine device for path: %q", mountPath)
} else {
for i := range mps {
if mps[i].Device == deviceName && mps[i].Path != slTarget {
refs = append(refs, mps[i].Path)
}
}
}
return refs, nil
}
// GetMountRefsByDev finds all references to the device provided
// by mountPath; returns a list of paths.
func GetMountRefsByDev(mounter Interface, mountPath string) ([]string, error) {
@ -239,34 +180,6 @@ func GetDeviceNameFromMount(mounter Interface, mountPath string) (string, int, e
return device, refCount, nil
}
// getDeviceNameFromMount find the device name from /proc/mounts in which
// the mount path reference should match the given plugin directory. In case no mount path reference
// matches, returns the volume name taken from its given mountPath
func getDeviceNameFromMount(mounter Interface, mountPath, pluginDir string) (string, error) {
refs, err := GetMountRefs(mounter, mountPath)
if err != nil {
glog.V(4).Infof("GetMountRefs failed for mount path %q: %v", mountPath, err)
return "", err
}
if len(refs) == 0 {
glog.V(4).Infof("Directory %s is not mounted", mountPath)
return "", fmt.Errorf("directory %s is not mounted", mountPath)
}
basemountPath := path.Join(pluginDir, MountsInGlobalPDPath)
for _, ref := range refs {
if strings.HasPrefix(ref, basemountPath) {
volumeID, err := filepath.Rel(basemountPath, ref)
if err != nil {
glog.Errorf("Failed to get volume id from mount %s - %v", mountPath, err)
return "", err
}
return volumeID, nil
}
}
return path.Base(mountPath), nil
}
// IsNotMountPoint determines if a directory is a mountpoint.
// It should return ErrNotExist when the directory does not exist.
// This method uses the List() of all mountpoints

View file

@ -22,6 +22,8 @@ import (
"fmt"
"os"
"os/exec"
"path"
"path/filepath"
"strconv"
"strings"
"syscall"
@ -42,6 +44,9 @@ const (
procMountsPath = "/proc/mounts"
// Location of the mountinfo file
procMountInfoPath = "/proc/self/mountinfo"
)
const (
// 'fsck' found errors and corrected them
fsckErrorsCorrected = 1
// 'fsck' found errors but exited without correcting them
@ -68,12 +73,12 @@ func New(mounterPath string) Interface {
// Mount mounts source to target as fstype with given options. 'source' and 'fstype' must
// be an emtpy string in case it's not required, e.g. for remount, or for auto filesystem
// type, where kernel handles fstype for you. The mount 'options' is a list of options,
// type, where kernel handles fs type for you. The mount 'options' is a list of options,
// currently come from mount(8), e.g. "ro", "remount", "bind", etc. If no more option is
// required, call Mount with an empty string list or nil.
func (mounter *Mounter) Mount(source string, target string, fstype string, options []string) error {
// Path to mounter binary if containerized mounter is needed. Otherwise, it is set to empty.
// All Linux distros are expected to be shipped with a mount utility that a support bind mounts.
// All Linux distros are expected to be shipped with a mount utility that an support bind mounts.
mounterPath := ""
bind, bindRemountOpts := isBind(options)
if bind {
@ -141,6 +146,41 @@ func (m *Mounter) doMount(mounterPath string, mountCmd string, source string, ta
return err
}
// GetMountRefs finds all other references to the device referenced
// by mountPath; returns a list of paths.
func GetMountRefs(mounter Interface, mountPath string) ([]string, error) {
mps, err := mounter.List()
if err != nil {
return nil, err
}
// Find the device name.
deviceName := ""
// If mountPath is symlink, need get its target path.
slTarget, err := filepath.EvalSymlinks(mountPath)
if err != nil {
slTarget = mountPath
}
for i := range mps {
if mps[i].Path == slTarget {
deviceName = mps[i].Device
break
}
}
// Find all references to the device.
var refs []string
if deviceName == "" {
glog.Warningf("could not determine device for path: %q", mountPath)
} else {
for i := range mps {
if mps[i].Device == deviceName && mps[i].Path != slTarget {
refs = append(refs, mps[i].Path)
}
}
}
return refs, nil
}
// detectSystemd returns true if OS runs with systemd as init. When not sure
// (permission errors, ...), it returns false.
// There may be different ways how to detect systemd, this one makes sure that
@ -252,29 +292,17 @@ func (mounter *Mounter) DeviceOpened(pathname string) (bool, error) {
// PathIsDevice uses FileInfo returned from os.Stat to check if path refers
// to a device.
func (mounter *Mounter) PathIsDevice(pathname string) (bool, error) {
pathType, err := mounter.GetFileType(pathname)
isDevice := pathType == FileTypeCharDev || pathType == FileTypeBlockDev
return isDevice, err
return pathIsDevice(pathname)
}
func exclusiveOpenFailsOnDevice(pathname string) (bool, error) {
var isDevice bool
finfo, err := os.Stat(pathname)
if os.IsNotExist(err) {
isDevice = false
}
// err in call to os.Stat
isDevice, err := pathIsDevice(pathname)
if err != nil {
return false, fmt.Errorf(
"PathIsDevice failed for path %q: %v",
pathname,
err)
}
// path refers to a device
if finfo.Mode()&os.ModeDevice != 0 {
isDevice = true
}
if !isDevice {
glog.Errorf("Path %q is not refering to a device.", pathname)
return false, nil
@ -294,11 +322,56 @@ func exclusiveOpenFailsOnDevice(pathname string) (bool, error) {
return false, errno
}
func pathIsDevice(pathname string) (bool, error) {
finfo, err := os.Stat(pathname)
if os.IsNotExist(err) {
return false, nil
}
// err in call to os.Stat
if err != nil {
return false, err
}
// path refers to a device
if finfo.Mode()&os.ModeDevice != 0 {
return true, nil
}
// path does not refer to device
return false, nil
}
//GetDeviceNameFromMount: given a mount point, find the device name from its global mount point
func (mounter *Mounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) {
return getDeviceNameFromMount(mounter, mountPath, pluginDir)
}
// getDeviceNameFromMount find the device name from /proc/mounts in which
// the mount path reference should match the given plugin directory. In case no mount path reference
// matches, returns the volume name taken from its given mountPath
func getDeviceNameFromMount(mounter Interface, mountPath, pluginDir string) (string, error) {
refs, err := GetMountRefs(mounter, mountPath)
if err != nil {
glog.V(4).Infof("GetMountRefs failed for mount path %q: %v", mountPath, err)
return "", err
}
if len(refs) == 0 {
glog.V(4).Infof("Directory %s is not mounted", mountPath)
return "", fmt.Errorf("directory %s is not mounted", mountPath)
}
basemountPath := path.Join(pluginDir, MountsInGlobalPDPath)
for _, ref := range refs {
if strings.HasPrefix(ref, basemountPath) {
volumeID, err := filepath.Rel(basemountPath, ref)
if err != nil {
glog.Errorf("Failed to get volume id from mount %s - %v", mountPath, err)
return "", err
}
return volumeID, nil
}
}
return path.Base(mountPath), nil
}
func listProcMounts(mountFilePath string) ([]MountPoint, error) {
content, err := utilio.ConsistentRead(mountFilePath, maxListTries)
if err != nil {
@ -345,64 +418,9 @@ func parseProcMounts(content []byte) ([]MountPoint, error) {
}
func (mounter *Mounter) MakeRShared(path string) error {
return doMakeRShared(path, procMountInfoPath)
}
func (mounter *Mounter) GetFileType(pathname string) (FileType, error) {
var pathType FileType
finfo, err := os.Stat(pathname)
if os.IsNotExist(err) {
return pathType, fmt.Errorf("path %q does not exist", pathname)
}
// err in call to os.Stat
if err != nil {
return pathType, err
}
mode := finfo.Sys().(*syscall.Stat_t).Mode
switch mode & syscall.S_IFMT {
case syscall.S_IFSOCK:
return FileTypeSocket, nil
case syscall.S_IFBLK:
return FileTypeBlockDev, nil
case syscall.S_IFCHR:
return FileTypeBlockDev, nil
case syscall.S_IFDIR:
return FileTypeDirectory, nil
case syscall.S_IFREG:
return FileTypeFile, nil
}
return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device")
}
func (mounter *Mounter) MakeDir(pathname string) error {
err := os.MkdirAll(pathname, os.FileMode(0755))
if err != nil {
if !os.IsExist(err) {
return err
}
}
return nil
}
func (mounter *Mounter) MakeFile(pathname string) error {
f, err := os.OpenFile(pathname, os.O_CREATE, os.FileMode(0644))
defer f.Close()
if err != nil {
if !os.IsExist(err) {
return err
}
}
return nil
}
func (mounter *Mounter) ExistsPath(pathname string) bool {
_, err := os.Stat(pathname)
if err != nil {
return false
}
return true
mountCmd := defaultMountCommand
mountArgs := []string{}
return doMakeRShared(path, procMountInfoPath, mountCmd, mountArgs)
}
// formatAndMount uses unix utils to format and mount the given disk
@ -471,7 +489,7 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
return mountErr
}
// getDiskFormat uses 'lsblk' to see if the given disk is unformated
// diskLooksUnformatted uses 'lsblk' to see if the given disk is unformated
func (mounter *SafeFormatAndMount) getDiskFormat(disk string) (string, error) {
args := []string{"-n", "-o", "FSTYPE", disk}
glog.V(4).Infof("Attempting to determine if disk %q is formatted using lsblk with args: (%v)", disk, args)
@ -573,7 +591,7 @@ func parseMountInfo(filename string) ([]mountInfo, error) {
// path is shared and bind-mounts it as rshared if needed. mountCmd and
// mountArgs are expected to contain mount-like command, doMakeRShared will add
// '--bind <path> <path>' and '--make-rshared <path>' to mountArgs.
func doMakeRShared(path string, mountInfoFilename string) error {
func doMakeRShared(path string, mountInfoFilename string, mountCmd string, mountArgs []string) error {
shared, err := isShared(path, mountInfoFilename)
if err != nil {
return err

View file

@ -18,10 +18,6 @@ limitations under the License.
package mount
import (
"errors"
)
type Mounter struct {
mounterPath string
}
@ -43,6 +39,12 @@ func (mounter *Mounter) Unmount(target string) error {
return nil
}
// GetMountRefs finds all other references to the device referenced
// by mountPath; returns a list of paths.
func GetMountRefs(mounter Interface, mountPath string) ([]string, error) {
return []string{}, nil
}
func (mounter *Mounter) List() ([]MountPoint, error) {
return []MountPoint{}, nil
}
@ -63,6 +65,10 @@ func (mounter *Mounter) GetDeviceNameFromMount(mountPath, pluginDir string) (str
return "", nil
}
func getDeviceNameFromMount(mounter Interface, mountPath, pluginDir string) (string, error) {
return "", nil
}
func (mounter *Mounter) DeviceOpened(pathname string) (bool, error) {
return false, nil
}
@ -82,19 +88,3 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
func (mounter *SafeFormatAndMount) diskLooksUnformatted(disk string) (bool, error) {
return true, nil
}
func (mounter *Mounter) GetFileType(pathname string) (FileType, error) {
return FileType("fake"), errors.New("not implemented")
}
func (mounter *Mounter) MakeDir(pathname string) error {
return nil
}
func (mounter *Mounter) MakeFile(pathname string) error {
return nil
}
func (mounter *Mounter) ExistsPath(pathname string) bool {
return true
}

View file

@ -22,10 +22,10 @@ import (
"fmt"
"os"
"os/exec"
"path"
"path/filepath"
"strconv"
"strings"
"syscall"
"github.com/golang/glog"
)
@ -75,28 +75,8 @@ func (mounter *Mounter) Mount(source string, target string, fstype string, optio
return nil
}
// currently only cifs mount is supported
if strings.ToLower(fstype) != "cifs" {
return fmt.Errorf("azureMount: only cifs mount is supported now, fstype: %q, mounting source (%q), target (%q), with options (%q)", fstype, source, target, options)
}
cmdLine := fmt.Sprintf(`$User = "%s";$PWord = ConvertTo-SecureString -String "%s" -AsPlainText -Force;`+
`$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $PWord`,
options[0], options[1])
driverLetter, err := getAvailableDriveLetter()
if err != nil {
return err
}
bindSource = driverLetter + ":"
cmdLine += fmt.Sprintf(";New-SmbGlobalMapping -LocalPath %s -RemotePath %s -Credential $Credential", bindSource, source)
if output, err := exec.Command("powershell", "/c", cmdLine).CombinedOutput(); err != nil {
// we don't return error here, even though New-SmbGlobalMapping failed, we still make it successful,
// will return error when Windows 2016 RS3 is ready on azure
glog.Errorf("azureMount: SmbGlobalMapping failed: %v, only SMB mount is supported now, output: %q", err, string(output))
return os.MkdirAll(target, 0755)
}
// empty implementation for mounting azure file
return os.MkdirAll(target, 0755)
}
if output, err := exec.Command("cmd", "/c", "mklink", "/D", target, bindSource).CombinedOutput(); err != nil {
@ -118,6 +98,16 @@ func (mounter *Mounter) Unmount(target string) error {
return nil
}
// GetMountRefs finds all other references to the device(drive) referenced
// by mountPath; returns a list of paths.
func GetMountRefs(mounter Interface, mountPath string) ([]string, error) {
refs, err := getAllParentLinks(normalizeWindowsPath(mountPath))
if err != nil {
return nil, err
}
return refs, nil
}
// List returns a list of all mounted filesystems. todo
func (mounter *Mounter) List() ([]MountPoint, error) {
return []MountPoint{}, nil
@ -152,6 +142,33 @@ func (mounter *Mounter) GetDeviceNameFromMount(mountPath, pluginDir string) (str
return getDeviceNameFromMount(mounter, mountPath, pluginDir)
}
// getDeviceNameFromMount find the device(drive) name in which
// the mount path reference should match the given plugin directory. In case no mount path reference
// matches, returns the volume name taken from its given mountPath
func getDeviceNameFromMount(mounter Interface, mountPath, pluginDir string) (string, error) {
refs, err := GetMountRefs(mounter, mountPath)
if err != nil {
glog.V(4).Infof("GetMountRefs failed for mount path %q: %v", mountPath, err)
return "", err
}
if len(refs) == 0 {
return "", fmt.Errorf("directory %s is not mounted", mountPath)
}
basemountPath := normalizeWindowsPath(path.Join(pluginDir, MountsInGlobalPDPath))
for _, ref := range refs {
if strings.Contains(ref, basemountPath) {
volumeID, err := filepath.Rel(normalizeWindowsPath(basemountPath), ref)
if err != nil {
glog.Errorf("Failed to get volume id from mount %s - %v", mountPath, err)
return "", err
}
return volumeID, nil
}
}
return path.Base(mountPath), nil
}
// DeviceOpened determines if the device is in use elsewhere
func (mounter *Mounter) DeviceOpened(pathname string) (bool, error) {
return false, nil
@ -168,67 +185,6 @@ func (mounter *Mounter) MakeRShared(path string) error {
return nil
}
// GetFileType checks for sockets/block/character devices
func (mounter *Mounter) GetFileType(pathname string) (FileType, error) {
var pathType FileType
info, err := os.Stat(pathname)
if os.IsNotExist(err) {
return pathType, fmt.Errorf("path %q does not exist", pathname)
}
// err in call to os.Stat
if err != nil {
return pathType, err
}
mode := info.Sys().(*syscall.Win32FileAttributeData).FileAttributes
switch mode & syscall.S_IFMT {
case syscall.S_IFSOCK:
return FileTypeSocket, nil
case syscall.S_IFBLK:
return FileTypeBlockDev, nil
case syscall.S_IFCHR:
return FileTypeCharDev, nil
case syscall.S_IFDIR:
return FileTypeDirectory, nil
case syscall.S_IFREG:
return FileTypeFile, nil
}
return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device")
}
// MakeFile creates a new directory
func (mounter *Mounter) MakeDir(pathname string) error {
err := os.MkdirAll(pathname, os.FileMode(0755))
if err != nil {
if !os.IsExist(err) {
return err
}
}
return nil
}
// MakeFile creates an empty file
func (mounter *Mounter) MakeFile(pathname string) error {
f, err := os.OpenFile(pathname, os.O_CREATE, os.FileMode(0644))
defer f.Close()
if err != nil {
if !os.IsExist(err) {
return err
}
}
return nil
}
// ExistsPath checks whether the path exists
func (mounter *Mounter) ExistsPath(pathname string) bool {
_, err := os.Stat(pathname)
if err != nil {
return false
}
return true
}
func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, fstype string, options []string) error {
// Try to mount the disk
glog.V(4).Infof("Attempting to formatAndMount disk: %s %s %s", fstype, source, target)
@ -260,20 +216,6 @@ func normalizeWindowsPath(path string) string {
return normalizedPath
}
func getAvailableDriveLetter() (string, error) {
cmd := "$used = Get-PSDrive | Select-Object -Expand Name | Where-Object { $_.Length -eq 1 }"
cmd += ";$drive = 67..90 | ForEach-Object { [string][char]$_ } | Where-Object { $used -notcontains $_ } | Select-Object -First 1;$drive"
output, err := exec.Command("powershell", "/c", cmd).CombinedOutput()
if err != nil {
return "", fmt.Errorf("getAvailableDriveLetter failed: %v, output: %q", err, string(output))
}
if len(output) == 0 {
return "", fmt.Errorf("azureMount: there is no available drive letter now")
}
return string(output)[:1], nil
}
// ValidateDiskNumber : disk number should be a number in [0, 99]
func ValidateDiskNumber(disk string) error {
diskNum, err := strconv.Atoi(disk)
@ -300,3 +242,30 @@ func getDriveLetterByDiskNumber(diskNum string, exec Exec) (string, error) {
}
return string(output)[:1], nil
}
// getAllParentLinks walks all symbolic links and return all the parent targets recursively
func getAllParentLinks(path string) ([]string, error) {
const maxIter = 255
links := []string{}
for {
links = append(links, path)
if len(links) > maxIter {
return links, fmt.Errorf("unexpected length of parent links: %v", links)
}
fi, err := os.Lstat(path)
if err != nil {
return links, fmt.Errorf("Lstat: %v", err)
}
if fi.Mode()&os.ModeSymlink == 0 {
break
}
path, err = os.Readlink(path)
if err != nil {
return links, fmt.Errorf("Readlink error: %v", err)
}
}
return links, nil
}

View file

@ -19,6 +19,8 @@ limitations under the License.
package mount
import (
"fmt"
"os/exec"
"testing"
)
@ -69,3 +71,70 @@ func TestValidateDiskNumber(t *testing.T) {
t.Errorf("TestValidateDiskNumber test failed, disk number : %s", diskNum)
}
}
func makeLink(link, target string) error {
if output, err := exec.Command("cmd", "/c", "mklink", "/D", link, target).CombinedOutput(); err != nil {
return fmt.Errorf("mklink failed: %v, link(%q) target(%q) output: %q", err, link, target, string(output))
}
return nil
}
func removeLink(link string) error {
if output, err := exec.Command("cmd", "/c", "rmdir", link).CombinedOutput(); err != nil {
return fmt.Errorf("rmdir failed: %v, output: %q", err, string(output))
}
return nil
}
func setEquivalent(set1, set2 []string) bool {
map1 := make(map[string]bool)
map2 := make(map[string]bool)
for _, s := range set1 {
map1[s] = true
}
for _, s := range set2 {
map2[s] = true
}
for s := range map1 {
if !map2[s] {
return false
}
}
for s := range map2 {
if !map1[s] {
return false
}
}
return true
}
// this func must run in admin mode, otherwise it will fail
func TestGetMountRefs(t *testing.T) {
fm := &FakeMounter{MountPoints: []MountPoint{}}
mountPath := `c:\secondmountpath`
expectedRefs := []string{`c:\`, `c:\firstmountpath`, mountPath}
// remove symbolic links first
for i := 1; i < len(expectedRefs); i++ {
removeLink(expectedRefs[i])
}
// create symbolic links
for i := 1; i < len(expectedRefs); i++ {
if err := makeLink(expectedRefs[i], expectedRefs[i-1]); err != nil {
t.Errorf("makeLink failed: %v", err)
}
}
if refs, err := GetMountRefs(fm, mountPath); err != nil || !setEquivalent(expectedRefs, refs) {
t.Errorf("getMountRefs(%q) = %v, error: %v; expected %v", mountPath, refs, err, expectedRefs)
}
// remove symbolic links
for i := 1; i < len(expectedRefs); i++ {
if err := removeLink(expectedRefs[i]); err != nil {
t.Errorf("removeLink failed: %v", err)
}
}
}

View file

@ -25,30 +25,78 @@ import (
"strings"
"github.com/golang/glog"
"k8s.io/kubernetes/pkg/util/nsenter"
"k8s.io/utils/exec"
)
const (
// hostProcMountsPath is the default mount path for rootfs
hostProcMountsPath = "/rootfs/proc/1/mounts"
// hostProcMountinfoPath is the default mount info path for rootfs
hostProcMountinfoPath = "/rootfs/proc/1/mountinfo"
)
// Currently, all docker containers receive their own mount namespaces.
// NsenterMounter works by executing nsenter to run commands in
// NsenterMounter is part of experimental support for running the kubelet
// in a container. Currently, all docker containers receive their own mount
// namespaces. NsenterMounter works by executing nsenter to run commands in
// the host's mount namespace.
//
// NsenterMounter requires:
//
// 1. Docker >= 1.6 due to the dependency on the slave propagation mode
// of the bind-mount of the kubelet root directory in the container.
// Docker 1.5 used a private propagation mode for bind-mounts, so mounts
// performed in the host's mount namespace do not propagate out to the
// bind-mount in this docker version.
// 2. The host's root filesystem must be available at /rootfs
// 3. The nsenter binary must be on the Kubelet process' PATH in the container's
// filesystem.
// 4. The Kubelet process must have CAP_SYS_ADMIN (required by nsenter); at
// the present, this effectively means that the kubelet is running in a
// privileged container.
// 5. The volume path used by the Kubelet must be the same inside and outside
// the container and be writable by the container (to initialize volume)
// contents. TODO: remove this requirement.
// 6. The host image must have mount, findmnt, and umount binaries in /bin,
// /usr/sbin, or /usr/bin
// 7. The host image should have systemd-run in /bin, /usr/sbin, or /usr/bin
// For more information about mount propagation modes, see:
// https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt
type NsenterMounter struct {
ne *nsenter.Nsenter
// a map of commands to their paths on the host filesystem
paths map[string]string
}
func NewNsenterMounter() *NsenterMounter {
return &NsenterMounter{ne: nsenter.NewNsenter()}
m := &NsenterMounter{
paths: map[string]string{
"mount": "",
"findmnt": "",
"umount": "",
"systemd-run": "",
},
}
// search for the mount command in other locations besides /usr/bin
for binary := range m.paths {
// default to root
m.paths[binary] = filepath.Join("/", binary)
for _, path := range []string{"/bin", "/usr/sbin", "/usr/bin"} {
binPath := filepath.Join(path, binary)
if _, err := os.Stat(filepath.Join(hostRootFsPath, binPath)); err != nil {
continue
}
m.paths[binary] = binPath
break
}
// TODO: error, so that the kubelet can stop if the mounts don't exist
// (don't forget that systemd-run is optional)
}
return m
}
// NsenterMounter implements mount.Interface
var _ = Interface(&NsenterMounter{})
const (
hostRootFsPath = "/rootfs"
hostProcMountsPath = "/rootfs/proc/1/mounts"
hostProcMountinfoPath = "/rootfs/proc/1/mountinfo"
hostMountNamespacePath = "/rootfs/proc/1/ns/mnt"
nsenterPath = "nsenter"
)
// Mount runs mount(8) in the host's root mount namespace. Aside from this
// aspect, Mount has the same semantics as the mounter returned by mount.New()
func (n *NsenterMounter) Mount(source string, target string, fstype string, options []string) error {
@ -68,22 +116,26 @@ func (n *NsenterMounter) Mount(source string, target string, fstype string, opti
// doNsenterMount nsenters the host's mount namespace and performs the
// requested mount.
func (n *NsenterMounter) doNsenterMount(source, target, fstype string, options []string) error {
glog.V(5).Infof("nsenter mount %s %s %s %v", source, target, fstype, options)
cmd, args := n.makeNsenterArgs(source, target, fstype, options)
outputBytes, err := n.ne.Exec(cmd, args).CombinedOutput()
glog.V(5).Infof("nsenter Mounting %s %s %s %v", source, target, fstype, options)
args := n.makeNsenterArgs(source, target, fstype, options)
glog.V(5).Infof("Mount command: %v %v", nsenterPath, args)
exec := exec.New()
outputBytes, err := exec.Command(nsenterPath, args...).CombinedOutput()
if len(outputBytes) != 0 {
glog.V(5).Infof("Output of mounting %s to %s: %v", source, target, string(outputBytes))
}
return err
}
// makeNsenterArgs makes a list of argument to nsenter in order to do the
// requested mount.
func (n *NsenterMounter) makeNsenterArgs(source, target, fstype string, options []string) (string, []string) {
mountCmd := n.ne.AbsHostPath("mount")
func (n *NsenterMounter) makeNsenterArgs(source, target, fstype string, options []string) []string {
mountCmd := n.absHostPath("mount")
mountArgs := makeMountArgs(source, target, fstype, options)
if systemdRunPath, hasSystemd := n.ne.SupportsSystemd(); hasSystemd {
if systemdRunPath, hasSystemd := n.paths["systemd-run"]; hasSystemd {
// Complete command line:
// nsenter --mount=/rootfs/proc/1/ns/mnt -- /bin/systemd-run --description=... --scope -- /bin/mount -t <type> <what> <where>
// Expected flow is:
@ -113,20 +165,34 @@ func (n *NsenterMounter) makeNsenterArgs(source, target, fstype string, options
// No code here, mountCmd and mountArgs use /bin/mount
}
return mountCmd, mountArgs
nsenterArgs := []string{
"--mount=" + hostMountNamespacePath,
"--",
mountCmd,
}
nsenterArgs = append(nsenterArgs, mountArgs...)
return nsenterArgs
}
// Unmount runs umount(8) in the host's mount namespace.
func (n *NsenterMounter) Unmount(target string) error {
args := []string{target}
args := []string{
"--mount=" + hostMountNamespacePath,
"--",
n.absHostPath("umount"),
target,
}
// No need to execute systemd-run here, it's enough that unmount is executed
// in the host's mount namespace. It will finish appropriate fuse daemon(s)
// running in any scope.
glog.V(5).Infof("nsenter unmount args: %v", args)
outputBytes, err := n.ne.Exec("umount", args).CombinedOutput()
glog.V(5).Infof("Unmount command: %v %v", nsenterPath, args)
exec := exec.New()
outputBytes, err := exec.Command(nsenterPath, args...).CombinedOutput()
if len(outputBytes) != 0 {
glog.V(5).Infof("Output of unmounting %s: %v", target, string(outputBytes))
}
return err
}
@ -141,7 +207,7 @@ func (m *NsenterMounter) IsNotMountPoint(dir string) (bool, error) {
func (*NsenterMounter) IsMountPointMatch(mp MountPoint, dir string) bool {
deletedDir := fmt.Sprintf("%s\\040(deleted)", dir)
return (mp.Path == dir) || (mp.Path == deletedDir)
return ((mp.Path == dir) || (mp.Path == deletedDir))
}
// IsLikelyNotMountPoint determines whether a path is a mountpoint by calling findmnt
@ -161,9 +227,11 @@ func (n *NsenterMounter) IsLikelyNotMountPoint(file string) (bool, error) {
// the first of multiple possible mountpoints using --first-only.
// Also add fstype output to make sure that the output of target file will give the full path
// TODO: Need more refactoring for this function. Track the solution with issue #26996
args := []string{"-o", "target,fstype", "--noheadings", "--first-only", "--target", file}
glog.V(5).Infof("nsenter findmnt args: %v", args)
out, err := n.ne.Exec("findmnt", args).CombinedOutput()
args := []string{"--mount=" + hostMountNamespacePath, "--", n.absHostPath("findmnt"), "-o", "target,fstype", "--noheadings", "--first-only", "--target", file}
glog.V(5).Infof("findmnt command: %v %v", nsenterPath, args)
exec := exec.New()
out, err := exec.Command(nsenterPath, args...).CombinedOutput()
if err != nil {
glog.V(2).Infof("Failed findmnt command for path %s: %v", file, err)
// Different operating systems behave differently for paths which are not mount points.
@ -209,9 +277,7 @@ func (n *NsenterMounter) DeviceOpened(pathname string) (bool, error) {
// PathIsDevice uses FileInfo returned from os.Stat to check if path refers
// to a device.
func (n *NsenterMounter) PathIsDevice(pathname string) (bool, error) {
pathType, err := n.GetFileType(pathname)
isDevice := pathType == FileTypeCharDev || pathType == FileTypeBlockDev
return isDevice, err
return pathIsDevice(pathname)
}
//GetDeviceNameFromMount given a mount point, find the volume id from checking /proc/mounts
@ -219,54 +285,20 @@ func (n *NsenterMounter) GetDeviceNameFromMount(mountPath, pluginDir string) (st
return getDeviceNameFromMount(n, mountPath, pluginDir)
}
func (n *NsenterMounter) absHostPath(command string) string {
path, ok := n.paths[command]
if !ok {
return command
}
return path
}
func (n *NsenterMounter) MakeRShared(path string) error {
return doMakeRShared(path, hostProcMountinfoPath)
}
func (mounter *NsenterMounter) GetFileType(pathname string) (FileType, error) {
var pathType FileType
outputBytes, err := mounter.ne.Exec("stat", []string{"-L", `--printf "%F"`, pathname}).CombinedOutput()
if err != nil {
return pathType, err
nsenterCmd := nsenterPath
nsenterArgs := []string{
"--mount=" + hostMountNamespacePath,
"--",
n.absHostPath("mount"),
}
switch string(outputBytes) {
case "socket":
return FileTypeSocket, nil
case "character special file":
return FileTypeCharDev, nil
case "block special file":
return FileTypeBlockDev, nil
case "directory":
return FileTypeDirectory, nil
case "regular file":
return FileTypeFile, nil
}
return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device")
}
func (mounter *NsenterMounter) MakeDir(pathname string) error {
args := []string{"-p", pathname}
if _, err := mounter.ne.Exec("mkdir", args).CombinedOutput(); err != nil {
return err
}
return nil
}
func (mounter *NsenterMounter) MakeFile(pathname string) error {
args := []string{pathname}
if _, err := mounter.ne.Exec("touch", args).CombinedOutput(); err != nil {
return err
}
return nil
}
func (mounter *NsenterMounter) ExistsPath(pathname string) bool {
args := []string{pathname}
_, err := mounter.ne.Exec("ls", args).CombinedOutput()
if err == nil {
return true
}
return false
return doMakeRShared(path, hostProcMountinfoPath, nsenterCmd, nsenterArgs)
}

View file

@ -18,10 +18,6 @@ limitations under the License.
package mount
import (
"errors"
)
type NsenterMounter struct{}
func NewNsenterMounter() *NsenterMounter {
@ -69,19 +65,3 @@ func (*NsenterMounter) GetDeviceNameFromMount(mountPath, pluginDir string) (stri
func (*NsenterMounter) MakeRShared(path string) error {
return nil
}
func (*NsenterMounter) GetFileType(_ string) (FileType, error) {
return FileType("fake"), errors.New("not implemented")
}
func (*NsenterMounter) MakeDir(pathname string) error {
return nil
}
func (*NsenterMounter) MakeFile(pathname string) error {
return nil
}
func (*NsenterMounter) ExistsPath(pathname string) bool {
return true
}

View file

@ -12,13 +12,11 @@ go_library(
"doc.go",
"ipnet.go",
],
importpath = "k8s.io/kubernetes/pkg/util/net/sets",
)
go_test(
name = "go_default_test",
srcs = ["ipnet_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/net/sets",
library = ":go_default_library",
)

View file

@ -1,37 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"nsenter_unsupported.go",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"nsenter.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/util/nsenter",
visibility = ["//visibility:public"],
deps = [
"//vendor/k8s.io/utils/exec:go_default_library",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"//vendor/github.com/golang/glog:go_default_library",
],
"//conditions:default": [],
}),
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View file

@ -1,124 +0,0 @@
// +build linux
/*
Copyright 2017 The Kubernetes Authors.
Licensed 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.
*/
package nsenter
import (
"fmt"
"os"
"path/filepath"
"k8s.io/utils/exec"
"github.com/golang/glog"
)
const (
hostRootFsPath = "/rootfs"
// hostProcMountNsPath is the default mount namespace for rootfs
hostProcMountNsPath = "/rootfs/proc/1/ns/mnt"
// nsenterPath is the default nsenter command
nsenterPath = "nsenter"
)
// Nsenter is part of experimental support for running the kubelet
// in a container.
//
// Nsenter requires:
//
// 1. Docker >= 1.6 due to the dependency on the slave propagation mode
// of the bind-mount of the kubelet root directory in the container.
// Docker 1.5 used a private propagation mode for bind-mounts, so mounts
// performed in the host's mount namespace do not propagate out to the
// bind-mount in this docker version.
// 2. The host's root filesystem must be available at /rootfs
// 3. The nsenter binary must be on the Kubelet process' PATH in the container's
// filesystem.
// 4. The Kubelet process must have CAP_SYS_ADMIN (required by nsenter); at
// the present, this effectively means that the kubelet is running in a
// privileged container.
// 5. The volume path used by the Kubelet must be the same inside and outside
// the container and be writable by the container (to initialize volume)
// contents. TODO: remove this requirement.
// 6. The host image must have "mount", "findmnt", "umount", "stat", "touch",
// "mkdir", "ls", "sh" and "chmod" binaries in /bin, /usr/sbin, or /usr/bin
// 7. The host image should have systemd-run in /bin, /usr/sbin, or /usr/bin
// For more information about mount propagation modes, see:
// https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt
type Nsenter struct {
// a map of commands to their paths on the host filesystem
paths map[string]string
}
// NewNsenter constructs a new instance of Nsenter
func NewNsenter() *Nsenter {
ne := &Nsenter{
paths: map[string]string{
"mount": "",
"findmnt": "",
"umount": "",
"systemd-run": "",
"stat": "",
"touch": "",
"mkdir": "",
"ls": "",
"sh": "",
"chmod": "",
},
}
// search for the required commands in other locations besides /usr/bin
for binary := range ne.paths {
// default to root
ne.paths[binary] = filepath.Join("/", binary)
for _, path := range []string{"/bin", "/usr/sbin", "/usr/bin"} {
binPath := filepath.Join(path, binary)
if _, err := os.Stat(filepath.Join(hostRootFsPath, binPath)); err != nil {
continue
}
ne.paths[binary] = binPath
break
}
// TODO: error, so that the kubelet can stop if the paths don't exist
// (don't forget that systemd-run is optional)
}
return ne
}
// Exec executes nsenter commands in hostProcMountNsPath mount namespace
func (ne *Nsenter) Exec(cmd string, args []string) exec.Cmd {
fullArgs := append([]string{fmt.Sprintf("--mount=%s", hostProcMountNsPath), "--"},
append([]string{ne.AbsHostPath(cmd)}, args...)...)
glog.V(5).Infof("Running nsenter command: %v %v", nsenterPath, fullArgs)
exec := exec.New()
return exec.Command(nsenterPath, fullArgs...)
}
// AbsHostPath returns the absolute runnable path for a specified command
func (ne *Nsenter) AbsHostPath(command string) string {
path, ok := ne.paths[command]
if !ok {
return command
}
return path
}
// SupportsSystemd checks whether command systemd-run exists
func (ne *Nsenter) SupportsSystemd() (string, bool) {
systemdRunPath, hasSystemd := ne.paths["systemd-run"]
return systemdRunPath, hasSystemd
}

View file

@ -1,50 +0,0 @@
// +build !linux
/*
Copyright 2017 The Kubernetes Authors.
Licensed 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.
*/
package nsenter
import (
"k8s.io/utils/exec"
)
// Nsenter is part of experimental support for running the kubelet
// in a container.
type Nsenter struct {
// a map of commands to their paths on the host filesystem
Paths map[string]string
}
// NewNsenter constructs a new instance of Nsenter
func NewNsenter() *Nsenter {
return &Nsenter{}
}
// Exec executes nsenter commands in hostProcMountNsPath mount namespace
func (ne *Nsenter) Exec(args ...string) exec.Cmd {
return nil
}
// AbsHostPath returns the absolute runnable path for a specified command
func (ne *Nsenter) AbsHostPath(command string) string {
return ""
}
// SupportsSystemd checks whether command systemd-run exists
func (ne *Nsenter) SupportsSystemd() (string, bool) {
return "", false
}

View file

@ -9,14 +9,12 @@ load(
go_library(
name = "go_default_library",
srcs = ["parsers.go"],
importpath = "k8s.io/kubernetes/pkg/util/parsers",
deps = ["//vendor/github.com/docker/distribution/reference:go_default_library"],
)
go_test(
name = "go_default_test",
srcs = ["parsers_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/parsers",
library = ":go_default_library",
)

View file

@ -9,14 +9,12 @@ load(
go_test(
name = "go_default_test",
srcs = ["pointer_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/pointer",
library = ":go_default_library",
)
go_library(
name = "go_default_library",
srcs = ["pointer.go"],
importpath = "k8s.io/kubernetes/pkg/util/pointer",
)
filegroup(

Some files were not shown because too many files have changed in this diff Show more